#include <stdio.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "freertos/queue.h"
#include "mqtt_client.h"
#include "driver/uart.h"
#include "esp_log.h"
#include "string.h"
#include "driver/gpio.h"
#include "CRC16.h"
#include "wifi.h"
#include "cJSON.h"
#include "get_time.h"
#include "mbedtls/md5.h"
#include "my_wss.h"
#include "BedSpread.h"
#include <math.h>
#include <time.h>
#include "nvs_flash.h"
#include "nvs.h"
#include "my_nvs.h"
#include "my_smartconfig.h"
#include "ota.h"

#define TAG1 "Bed"
#define BED_TXD_PIN (GPIO_NUM_23)
#define BED_RXD_PIN (GPIO_NUM_22)
#define BED_RTS_PIN (UART_PIN_NO_CHANGE)
#define BED_CTS_PIN (UART_PIN_NO_CHANGE)
#define BED_UART_NUM UART_NUM_2
// Read packet timeout
#define BED_PACKET_READ_TICS (100 / portTICK_PERIOD_MS)
#define BED_READ_TOUT (3)

TaskHandle_t BedSyncOnceHandle = NULL;
TaskHandle_t BedSyncWeekHandle = NULL;
TaskHandle_t BedChangeHandle = NULL;
TaskHandle_t BedRXTaskHandle = NULL;
volatile SemaphoreHandle_t xSemaphore = NULL;
volatile SemaphoreHandle_t xSemaphore2 = NULL;
int policy_tx = 0; // 策略控制标志位
int WifiTest = 0;  // 产测结果标志位 0-无产测 1-产测成功 2-产测失败
const int BED_RX_SIZE = 1024;
char Bed_Test_State[8] = {0};   // 测试报文指令是否正确
char Bed_Write_State[8] = {0};  // 写指令回复的功能位数组
char Bed_Read_State[8] = {0};   // 读指令回复的功能位数组
char Left_Body_State[8] = {0};  // 左体动状态
char Right_Body_State[8] = {0}; // 右体动状态
// char Bed_SyncPolicy_State[13] = {0}; // 同步策略操作标志位  0~3：开关，4~7：温度，8~11：律动 12:消费状态
char Bed_SyncPolicy_State[8] = {0}; // 同步策略操作标志位 0：bed_key，1~2左右模式，3~4左右温度，5~6左右时间，7指示灯
char Bed_Control_State[8] = {0};    // 控制参数标志位  0：bed_key，1~2左右模式，3~4左右温度，5~6左右时间，7指示灯
char BedSyncOnce_flag = 0;          // 一次性策略定时任务创建标志位
char BedSyncWeek_flag = 0;          // 周期性策略定时任务创建标志位
char BedChange_flag = 0;            // 状态改变上报任务创建标志位
// char Task_Create[2] = {0};           // 任务创建标志位
BedSpread Bed_Write = {
    .bed_key = 0,
    .left_uptemp = 28,
    .left_downtemp = 28,
    .right_uptemp = 28,
    .right_downtemp = 28,
    .left_mode = 0,
    .left_settemp = 28,
    .left_time = 0,
    .right_mode = 0,
    .right_settemp = 28,
    .right_time = 0,
    .LED = 0};      // 写指令回复数据
BedSpread Bed_Read; // 读指令回复数据
// BedSpread Bed_Test;  // 测试数据是否正确
BedSpread Bed_Test = {
    .left_uptemp = 28,
    .left_downtemp = 28,
    .right_uptemp = 28,
    .right_downtemp = 28};
BedSyncPolicy Bed_Sync; // 同步报文数据
BedControlTime Bed_Time = {
    .lefttime_set = 0,
    .righttime_set = 0,
    .left_starttime = 0,
    .left_endtime = 0,
    .right_starttime = 0,
    .right_endtime = 0};
int First_Bed_Read = 1; // 第一次读指令标志位
int write_pack = 13;
int read_pack = 19;         // 发送一次读取指令返回报文的个数
volatile int bed_rx = 0;    // 床垫读任务标志位，为0时代表无主动发送指令，为1时代表读取状态命令已发送
volatile int bed_tx = 0;    // 床垫控制标志位，为0代表无控制任务，为1代表有控制任务,为2代表有读取状态命令，3~8wifi状态指令
volatile int mqtt_read = 0; // 是否有来自mqtt的读取状态的指令
int bed_test = 0;           // 床垫产测标志位，0-不进入产测，1-进入产测
static portMUX_TYPE myMutex = portMUX_INITIALIZER_UNLOCKED;

// 串口初始化
void BedSpread_uart_init(void)
{
    xSemaphore = xSemaphoreCreateMutex();
    if (xSemaphore != NULL)
    {
        printf("信号量创建成功\n");
    }
    const int bed_uart_num = BED_UART_NUM;
    const uart_config_t bed_uart_config = {
        .baud_rate = 9600,
        .data_bits = UART_DATA_8_BITS,
        .parity = UART_PARITY_DISABLE,
        .stop_bits = UART_STOP_BITS_1,
        .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
        .source_clk = UART_SCLK_DEFAULT,
    };
    ESP_LOGI(TAG1, "Start application test and configure UART.");

    // 安装UART驱动程序
    ESP_ERROR_CHECK(uart_driver_install(bed_uart_num, BED_RX_SIZE, 0, 0, NULL, 0)); // intr_alloc_flags 用于分配中断的标志。一个或多个（ORred）
    // 设置uart参数
    ESP_ERROR_CHECK(uart_param_config(bed_uart_num, &bed_uart_config));
    // 设置uart引脚
    ESP_ERROR_CHECK(uart_set_pin(bed_uart_num, BED_TXD_PIN, BED_RXD_PIN, BED_RTS_PIN, BED_CTS_PIN));
    // 设置为常规UART模式
    ESP_ERROR_CHECK(uart_set_mode(bed_uart_num, UART_MODE_UART));
    // Set read timeout of UART TOUT feature
    ESP_ERROR_CHECK(uart_set_rx_timeout(bed_uart_num, BED_READ_TOUT));
}

// BED发送数据
void BED_send(const int port, const char *str, uint8_t length)
{
    if (uart_write_bytes(port, str, length) != length)
    {
        ESP_LOGE(TAG1, "Send data critical failure.");
        // 在此处添加处理发送失败的代码
        abort();
    }
}

// BED写指令
// void BedControl(esp_mqtt_client_handle_t *client, char *topic)
// {
//     // bed_rx = 1; // 有主动发送指令
//     printf("Start Write!!!\n");
//     char write_cmd[13] = {0x7A, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAF}; // 写操作指令
//     int length = sizeof(Bed_Write_State) / sizeof(Bed_Write_State[0]);
//     for (int i = 0; i < length; i++)
//     {
//         printf(" Bed_Write_State[%d] = %d\n", i, Bed_Write_State[i]);
//     }
//     Bed_Write.state = BinarrayToInt(Bed_Write_State, length);
//     printf("Bed_Write.state = %d\n", Bed_Write.state);
//     write_cmd[2] = Bed_Write.state;
//     write_cmd[3] = Bed_Write.left_uptemp;
//     write_cmd[4] = Bed_Write.right_uptemp;
//     write_cmd[5] = Bed_Write.left_downtemp;
//     write_cmd[6] = Bed_Write.right_downtemp;
//     write_cmd[7] = Bed_Write.left_VibFreq;
//     write_cmd[8] = Bed_Write.left_VibInt;
//     write_cmd[9] = Bed_Write.right_VibFreq;
//     write_cmd[10] = Bed_Write.right_VibInt;
//     int len = sizeof(write_cmd) / sizeof(write_cmd[0]);
//     printf("len = %d\n", len);
//     for (int i = 1; i < len - 2; i++)
//     {
//         write_cmd[len - 2] += write_cmd[i];
//     }
//     for (int i = 0; i < len; i++)
//     {
//         printf(" write_cmd[%d] = %02x\n", i, write_cmd[i]);
//     }
//     char *cbdata = (char *)malloc(BED_RX_SIZE); // 申请返回报文的空间
//     while (1)
//     {
//         if (xSemaphoreTake(xSemaphore, (TickType_t)10) == pdTRUE)
//         {
//             printf("获取到信号量\n");
//             BED_send(BED_UART_NUM, write_cmd, len);
//             printf("开始读取数据\n");
//             len = uart_read_bytes(BED_UART_NUM, cbdata, BED_RX_SIZE, BED_PACKET_READ_TICS);
//             if (len > 0)
//             {
//                 printf("读到数据\n");
//                 // for (int i = 0; i < len; i++)
//                 // {
//                 //     printf("cbdata[%d] = %02x\n", i, cbdata[i]);
//                 // }
//                 if (strncmp(&write_cmd[3], &cbdata[3], len - 5) == 0)
//                 {
//                     ESP_LOGI(TAG1, "write pack success!!!\n");
//                     // 发送写操作成功报文
//                     Publish_Reply_Message(*client, topic, true);
//                 }
//                 else
//                 {
//                     ESP_LOGE(TAG1, "write pack error!!!\n");
//                     // 发送写操作失败报文
//                     Publish_Reply_Message(*client, topic, false);
//                 }
//                 xSemaphoreGive(xSemaphore);
//                 printf("释放信号量\n");
//                 break;
//             }
//         }
//         else
//         {
//             printf("未获取到信号量\n");
//             vTaskDelay(10 / portTICK_PERIOD_MS);
//             BED_send(BED_UART_NUM, write_cmd, len);
//         }
//     }

//     // vTaskResume(BedRXTaskHandle);
//     free(cbdata);
//     // bed_rx = 0;
// }

// BED读取数值
int Bed_ReadState(esp_mqtt_client_handle_t *client, char *topic)
{
    while (bed_tx != 0)
    {
        vTaskDelay(5 / portTICK_PERIOD_MS);
    }
    bed_tx = 2;
    mqtt_read = 1;
    return 1;
}
// int Bed_ReadState(esp_mqtt_client_handle_t *client, char *topic)
// {

//     unsigned char check_sum = 0;                                                                          // 记载自己计算的校验和
//     unsigned char check = 0;                                                                              // 报文的校验和
//     char read_command[] = {0x7A, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xAF}; // 读操作指令
//     // 试试用sprintf转换成十进制
//     // vTaskDelete(BedRXTaskHandle);

//     while (1)
//     {
//         if (xSemaphoreTake(xSemaphore, (TickType_t)10) == pdTRUE)
//         {
//             printf("获取到信号量\n");
//             BED_send(BED_UART_NUM, read_command, 13);
//             printf("开始读取数据\n");
//             char *cbdata = (char *)malloc(BED_RX_SIZE); // 申请返回报文的空间
//             int len = uart_read_bytes(BED_UART_NUM, cbdata, BED_RX_SIZE, BED_PACKET_READ_TICS);
//             if (len > 0)
//             {
//                 printf("读到数据\n");
//                 for (int i = 1; i < (len - 3); i++)
//                 {
//                     check_sum += cbdata[i];
//                 }
//                 check = cbdata[len - 2];
//                 if (cbdata[0] != 0x7a || cbdata[1] != 0x83 || cbdata[len - 1] != 0xaf || check != check_sum)
//                 {
//                     printf("Bed_Read_Error\n");
//                     // 回复失败消息
//                 }
//                 else
//                 {
//                     // 处理成功的情况
//                     hexToBin(cbdata[2], Bed_Read_State);
//                     for (int i = 0; i < 19; i++)
//                     {
//                         printf("cbdata[%d] = %02x\n", i, cbdata[i]);
//                     }
//                     // 当首次连接时读取床垫控制板中的数据
//                     if (First_Bed_Read == 1)
//                     {
//                         First_Read = 0;
//                         Bed_Write_State[2] = 0;
//                         Bed_Write_State[3] = 0;
//                         Bed_Write_State[4] = 0;
//                         Bed_Write_State[6] = 0;
//                         Bed_Write_State[7] = 0;
//                         Bed_Write.left_uptemp = cbdata[3];
//                         Bed_Write.right_uptemp = cbdata[4];
//                         Bed_Write.left_downtemp = cbdata[5];
//                         Bed_Write.right_downtemp = cbdata[6];
//                         Bed_Write.left_VibFreq = cbdata[7];
//                         Bed_Write.left_VibInt = cbdata[8];
//                         Bed_Write.right_VibFreq = cbdata[9];
//                         Bed_Write.right_VibInt = cbdata[10];
//                         printf("first read BED success!!!\n");
//                     }

//                     Bed_Read.left_uptemp = cbdata[3];
//                     Bed_Read.right_uptemp = cbdata[4];
//                     Bed_Read.left_downtemp = cbdata[5];
//                     Bed_Read.right_downtemp = cbdata[6];
//                     Bed_Read.left_VibFreq = cbdata[7];
//                     Bed_Read.left_VibInt = cbdata[8];
//                     Bed_Read.right_VibFreq = cbdata[9];
//                     Bed_Read.right_VibInt = cbdata[10];
//                     Bed_Read.left_HR = cbdata[11];
//                     Bed_Read.left_RR = cbdata[12];
//                     // Bed_Read.left_Motion    = cbdata[13];
//                     hexToBin(cbdata[13], Left_Body_State);
//                     Bed_Read.right_HR = cbdata[14];
//                     Bed_Read.right_RR = cbdata[15];
//                     // Bed_Read.right_Motion   = cbdata[16];
//                     hexToBin(cbdata[16], Right_Body_State);
//                     Bed_Read.BedWet = cbdata[17];
//                     // 开始上报
//                     Publish_Bed_State(client, topic, cbdata);

//                     // 将时间戳转换为 struct tm 结构体
//                     struct tm *timeinfo = localtime((time_t *)&system_timestamp);

//                     // 获取星期几（0表示星期日，6表示星期六）
//                     int wday = timeinfo->tm_wday;

//                     // 输出结果
//                     char *weekdays[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
//                     printf("The work day of the week is: %s\n", weekdays[wday]);

//                     free(cbdata);
//                     // vTaskResume(BedRXTaskHandle);
//                     // if (xTaskCreate(bed_rx_task, "bed_rx_task", 2048, NULL, 2, &BedRXTaskHandle) == pdPASS)
//                     // {
//                     //     printf("Task created successfully.\n");
//                     // }
//                     // else
//                     // {
//                     //     printf("Failed to create task.\n");
//                     // }
//                     // uart_flush_input(BED_UART_NUM);
//                     xSemaphoreGive(xSemaphore);
//                     printf("释放信号量\n");
//                     return 1;
//                 }
//                 free(cbdata);
//             }
//             else
//             {
//                 free(cbdata);
//                 vTaskDelay(10 / portTICK_PERIOD_MS);
//                 BED_send(BED_UART_NUM, read_command, 13);
//             }
//         }
//         vTaskDelay(10 / portTICK_PERIOD_MS);
//     }
//     return 0;
// }

// // BED读任务
void Bed_ReadTask(void *arg)
{
    unsigned char check_sum = 0;                                                                          // 记载自己计算的校验和
    unsigned char check = 0;                                                                              // 报文的校验和
    char read_command[] = {0x7A, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xAF}; // 读操作指令
    char lastdata[20] = {0};
    while (1)
    {
        BED_send(BED_UART_NUM, read_command, 13);
        char *cbdata = (char *)malloc(BED_RX_SIZE); // 申请返回报文的空间

        int len = uart_read_bytes(BED_UART_NUM, cbdata, BED_RX_SIZE, BED_PACKET_READ_TICS);
        if (len > 0 && len % read_pack == 0)
        {
            int pack_num = len / read_pack; // 计算回复的报文数量
            // printf("Receive %d read_pack!!!\n", pack_num);
            // char *stop; // 用于strtol函数

            // for (int i = 0; i < len; i++)
            // {
            //     printf("cbdata[%d] = %02x\n", i, cbdata[i]);
            // }
            for (int a = 0; a < pack_num; a++)
            {
                check_sum = 0;                // 清零
                int displace = a * read_pack; // 要移位的个数
                for (int i = 1 + displace; i < (displace + read_pack - 3); i++)
                {
                    check_sum += cbdata[i];
                }
                check = cbdata[displace + read_pack - 2]; // 修正校验和计算位置
                // printf("check_sum = %02x , check = %02x\n", check_sum, check);
                if (cbdata[0 + displace] != 0x7a || cbdata[1 + displace] != 0x83 || cbdata[read_pack + displace - 1] != 0xaf || check != check_sum)
                {
                    printf("Bed_Read_Error\n");
                }
                else
                {
                    // printf("Bed_Read_Success!!\n");
                    // if (first_read)
                    // {
                    //     memcpy(lastdata, cbdata + displace, read_pack);
                    //     first_read = 0;
                    // }
                    // 处理成功的情况
                    hexToBin(cbdata[2 + displace], Bed_Read_State);
                    Bed_Read.left_uptemp = cbdata[3 + displace];
                    Bed_Read.right_uptemp = cbdata[4 + displace];
                    Bed_Read.left_downtemp = cbdata[5 + displace];
                    Bed_Read.right_downtemp = cbdata[6 + displace];
                    Bed_Read.left_VibFreq = cbdata[7 + displace];
                    Bed_Read.left_VibInt = cbdata[8 + displace];
                    Bed_Read.right_VibFreq = cbdata[9 + displace];
                    Bed_Read.right_VibInt = cbdata[10 + displace];
                    Bed_Read.left_HR = cbdata[11 + displace];
                    Bed_Read.left_RR = cbdata[12 + displace];
                    // Bed_Read.left_Motion    = cbdata[13];
                    hexToBin(cbdata[13 + displace], Left_Body_State);
                    Bed_Read.right_HR = cbdata[14 + displace];
                    Bed_Read.right_RR = cbdata[15 + displace];
                    // Bed_Read.right_Motion   = cbdata[16];
                    hexToBin(cbdata[16 + displace], Right_Body_State);
                    Bed_Read.BedWet = cbdata[17 + displace];
                    // 判断是否与上次数据一样
                    if (strncmp(lastdata, cbdata + displace, read_pack) == 0)
                    {
                        // printf("Same_ReadData\n");
                    }
                    else
                    {
                        printf("Different_ReadData\n");
                        memcpy(lastdata, cbdata + displace, read_pack); // 保留这一次的数据
                        for (int i = 0; i < 8; i++)
                        {
                            printf("Bed_Read_State[%d] = %c\n", i, Bed_Read_State[i]);
                        }
                        // 状态改变需要上报
                    }
                }
            }
        }
        free(cbdata);
        // 释放动态分配的内存
        vTaskDelay(500 / portTICK_PERIOD_MS); // 半秒读一次
    }
}

// 当状态改变时上报
void Publish_Bed_Change(void)
{
}

/**
 * @brief 上报床垫所有参数
 *
 * @param client
 * @param topic
 * @param cbdata 床垫的状态返回报文
 * @param hr_rr_body 心率、呼吸和体动标志位 1-不上报，0-上报 , 0~2:左，3~5：右
 */
void Publish_Bed_State(esp_mqtt_client_handle_t *client, char *topic, uint8_t *cbdata, char *hr_rr_body)
{
    size_t count = 0;
    nvs_handle_t my_handle;
    esp_err_t err;
    static const char *TAG2 = "Publish_Bed_State";
    mbedtls_md5_context md5_ctx;
    char wait_encrypt_str[255] = {0};
    unsigned char decrypt[16];
    char decrypt_cs[33];
    time_t left_time = 0;
    time_t right_time = 0;
    time_t elapsedtime = 0;
    char settimestring[20]; // 用于存放格式化后的时间字符串
    char elapsedtimestring[20];
    int hours, minutes, seconds;
    // 获取定时参数
    count = sizeof(BedControlTime);
    err = nvs_open(Bed_Storage, NVS_READWRITE, &my_handle);
    err = nvs_get_blob(my_handle, "Bed_Time", &Bed_Time, &count);
    if (err != ESP_OK)
    {
        printf("获取定时状态失败\n");
        printf("Error (%s) erasing NVS!\n", esp_err_to_name(err));
        Bed_Time.lefttime_set = 0;
        Bed_Time.righttime_set = 0;
        Bed_Time.left_starttime = 0;
        Bed_Time.left_endtime = 0;
        Bed_Time.right_starttime = 0;
        Bed_Time.right_endtime = 0;
    }
    nvs_close(my_handle);
    left_time = Bed_Time.left_endtime - Bed_Time.left_starttime;
    right_time = Bed_Time.right_endtime - Bed_Time.right_starttime;
    printf("left_time = %lld,right_time = %lld\n", left_time, right_time);
    cJSON *attributes = cJSON_CreateObject();
    cJSON *content;
    cJSON *sub_content;
    cJSON_AddStringToObject(attributes, "deviceType", "SmartDevice");
    cJSON_AddStringToObject(attributes, "subType", "RDBed");
    cJSON_AddStringToObject(attributes, "deviceMAC", mac_str);
    cJSON_AddStringToObject(attributes, "familyId", "0");
    cJSON_AddStringToObject(attributes, "groupId", "0");
    cJSON_AddStringToObject(attributes, "operate", "report");

    // content对象
    cJSON_AddItemToObject(attributes, "content", content = cJSON_CreateObject());
    cJSON_AddStringToObject(content, "type", "sensor");
    // 内部content
    cJSON_AddItemToObject(content, "content", sub_content = cJSON_CreateArray());
    cJSON *item_tmp = cJSON_CreateObject();
    // 填充内容
    char tempStr[8]; // 创建一个临时字符串来存储一个字符和一个null字符
    tempStr[1] = '\0';
    sprintf(tempStr, "%d", cbdata[3]);
    cJSON_AddStringToObject(item_tmp, "bed_key", tempStr);
    sprintf(tempStr, "%d", cbdata[4]);
    cJSON_AddStringToObject(item_tmp, "left_mode", tempStr);
    // 计算左区定时时间
    hours = left_time / 3600;
    minutes = (left_time % 3600) / 60;
    seconds = left_time % 60;
    // 将时间格式化为字符串
    snprintf(settimestring, sizeof(settimestring), "%02d:%02d:%02d", hours, minutes, seconds);
    cJSON_AddStringToObject(item_tmp, "left_time", settimestring);
    if (left_time != 0)
    {
        get_time(&system_timestamp);
        printf("计算已持续时间\n");
        elapsedtime = system_timestamp - Bed_Time.left_starttime;
        printf("elapsedtime = %lld秒", elapsedtime);
        hours = elapsedtime / 3600;
        minutes = (elapsedtime % 3600) / 60;
        seconds = elapsedtime % 60;
        snprintf(elapsedtimestring, sizeof(elapsedtimestring), "%02d:%02d:%02d", hours, minutes, seconds);
        cJSON_AddStringToObject(item_tmp, "left_elapsedtime", elapsedtimestring);
    }

    sprintf(tempStr, "%d", cbdata[6]);
    cJSON_AddStringToObject(item_tmp, "left_settemp", tempStr);
    sprintf(tempStr, "%d", cbdata[7]);
    cJSON_AddStringToObject(item_tmp, "left_nowtemp", tempStr);
    if (hr_rr_body[0] == 0)
    {
        sprintf(tempStr, "%d", cbdata[8]);
        cJSON_AddStringToObject(item_tmp, "left_HR", tempStr);
    }
    if (hr_rr_body[1] == 0)
    {
        sprintf(tempStr, "%d", cbdata[9]);
        cJSON_AddStringToObject(item_tmp, "left_RR", tempStr);
    }
    if (hr_rr_body[2] == 0)
    {
        hexToBin(cbdata[10], Left_Body_State); // 左床体动
        tempStr[0] = Left_Body_State[0];
        tempStr[1] = Left_Body_State[1];
        tempStr[2] = '\0';
        cJSON_AddStringToObject(item_tmp, "Left_Body_State", tempStr);
    }
    sprintf(tempStr, "%d", cbdata[11]);
    tempStr[1] = '\0';
    cJSON_AddStringToObject(item_tmp, "right_mode", tempStr);
    // 计算右区定时时间
    hours = right_time / 3600;
    minutes = (right_time % 3600) / 60;
    seconds = right_time % 60;
    snprintf(settimestring, sizeof(settimestring), "%02d:%02d:%02d", hours, minutes, seconds);
    cJSON_AddStringToObject(item_tmp, "right_time", settimestring);
    if (right_time != 0)
    {
        get_time(&system_timestamp);
        printf("计算已持续时间\n");
        elapsedtime = system_timestamp - Bed_Time.right_starttime;
        printf("elapsedtime = %lld秒", elapsedtime);
        hours = elapsedtime / 3600;
        minutes = (elapsedtime % 3600) / 60;
        seconds = elapsedtime % 60;
        snprintf(elapsedtimestring, sizeof(elapsedtimestring), "%02d:%02d:%02d", hours, minutes, seconds);
        cJSON_AddStringToObject(item_tmp, "right_elapsedtime", elapsedtimestring);
    }

    sprintf(tempStr, "%d", cbdata[13]);
    cJSON_AddStringToObject(item_tmp, "right_settemp", tempStr);
    sprintf(tempStr, "%d", cbdata[14]);
    cJSON_AddStringToObject(item_tmp, "right_nowtemp", tempStr);
    if (hr_rr_body[3] == 0)
    {
        sprintf(tempStr, "%d", cbdata[15]);
        cJSON_AddStringToObject(item_tmp, "right_HR", tempStr);
    }
    if (hr_rr_body[4] == 0)
    {
        sprintf(tempStr, "%d", cbdata[16]);
        cJSON_AddStringToObject(item_tmp, "right_RR", tempStr);
    }
    if (hr_rr_body[5] == 0)
    {
        hexToBin(cbdata[17], Right_Body_State); // 左床体动
        tempStr[0] = Right_Body_State[0];
        tempStr[1] = Right_Body_State[1];
        tempStr[2] = '\0';
        cJSON_AddStringToObject(item_tmp, "Right_Body_State", tempStr);
    }
    sprintf(tempStr, "%d", cbdata[18]);
    cJSON_AddStringToObject(item_tmp, "LED", tempStr);
    // 将内容填入sub_content
    cJSON_AddItemToArray(sub_content, item_tmp);

    char source[] = "Alive";
    cJSON_AddStringToObject(attributes, "source", source);
    cJSON_AddStringToObject(attributes, "version", "v0.1");
    get_time(&system_timestamp);
    ESP_LOGI(TAG1, "The timestamp is %lld \n", system_timestamp);
    char timestamp[14];
    sprintf(timestamp, "%lld", system_timestamp);
    cJSON_AddStringToObject(attributes, "timestamp", timestamp);
    // md5校验
    strcat(wait_encrypt_str, "Alive");
    strcat(wait_encrypt_str, source);
    strcat(wait_encrypt_str, timestamp);
    mbedtls_md5_init(&md5_ctx);
    mbedtls_md5_starts(&md5_ctx);
    mbedtls_md5_update(&md5_ctx, (unsigned char *)wait_encrypt_str, strlen((char *)wait_encrypt_str));
    mbedtls_md5_finish(&md5_ctx, decrypt);
    sprintf(decrypt_cs, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", decrypt[0], decrypt[1], decrypt[2], decrypt[3], decrypt[4], decrypt[5], decrypt[6], decrypt[7], decrypt[8], decrypt[9],
            decrypt[10], decrypt[11], decrypt[12], decrypt[13], decrypt[14], decrypt[15]);
    mbedtls_md5_free(&md5_ctx);
    cJSON_AddStringToObject(attributes, "sign", (char *)decrypt_cs);
    cJSON_AddStringToObject(attributes, "append", cjson_data.append);
    char *ptr = cJSON_Print(attributes);
    // 发布
    int msg_id = esp_mqtt_client_publish(client, topic, ptr, 0, 0, 0);
    ESP_LOGI(TAG2, "sent publish successful, msg_id=%d", msg_id);
    if (ptr != NULL)
    {
        cJSON_free(ptr);
        ptr = NULL;
    }
    cJSON_Delete(attributes);
}

// 上报床垫所有参数
// void Publish_Bed_State(esp_mqtt_client_handle_t *client, char *topic, char *cbdata)
// {
//     static const char *TAG2 = "Publish_Bed_State";
//     mbedtls_md5_context md5_ctx;
//     char wait_encrypt_str[255] = {0};
//     unsigned char decrypt[16];
//     char decrypt_cs[33];

//     cJSON *attributes = cJSON_CreateObject();
//     cJSON *content;
//     cJSON_AddStringToObject(attributes, "deviceType", "SmartDevice");
//     cJSON_AddStringToObject(attributes, "subType", "RDBed");
//     cJSON_AddStringToObject(attributes, "deviceMAC", mac_str);
//     cJSON_AddStringToObject(attributes, "familyId", "0");
//     cJSON_AddStringToObject(attributes, "groupId", "0");
//     cJSON_AddStringToObject(attributes, "operate", "report");

//     // content对象
//     cJSON_AddItemToObject(attributes, "content", content = cJSON_CreateObject());
//     // char temp_range = Bed_Read_State[0] * 10 + Bed_Read_State[1];
//     // printf("temp_range = %c\n", temp_range);
//     // char temp[1];
//     // cJSON_AddStringToObject(content, "temp_range", temp);
//     char tempStr[8];                // 创建一个临时字符串来存储一个字符和一个null字符
//     tempStr[0] = Bed_Read_State[0]; // 将字符复制到临时字符串
//     tempStr[1] = Bed_Read_State[1];
//     tempStr[2] = '\0';
//     cJSON_AddStringToObject(content, "temp_range", tempStr);
//     tempStr[0] = Bed_Read_State[2]; // 将字符复制到临时字符串
//     tempStr[1] = '\0';              // 添加null字符以结束字符串
//     cJSON_AddStringToObject(content, "left_upkey", tempStr);
//     tempStr[0] = Bed_Read_State[3];
//     cJSON_AddStringToObject(content, "right_upkey", tempStr);
//     tempStr[0] = Bed_Read_State[4];
//     cJSON_AddStringToObject(content, "cost", tempStr);
//     tempStr[0] = Bed_Read_State[5];
//     cJSON_AddStringToObject(content, "mode", tempStr);
//     tempStr[0] = Bed_Read_State[6];
//     cJSON_AddStringToObject(content, "left_downkey", tempStr);
//     tempStr[0] = Bed_Read_State[7];
//     cJSON_AddStringToObject(content, "right_downkey", tempStr);
//     sprintf(tempStr, "%d", cbdata[3]);
//     cJSON_AddStringToObject(content, "left_uptemp", tempStr);
//     sprintf(tempStr, "%d", cbdata[4]);
//     cJSON_AddStringToObject(content, "right_uptemp", tempStr);
//     sprintf(tempStr, "%d", cbdata[5]);
//     cJSON_AddStringToObject(content, "left_downtemp", tempStr);
//     sprintf(tempStr, "%d", cbdata[6]);
//     cJSON_AddStringToObject(content, "right_downtemp", tempStr);
//     sprintf(tempStr, "%d", cbdata[7]);
//     cJSON_AddStringToObject(content, "left_VibFreq", tempStr);
//     sprintf(tempStr, "%d", cbdata[8]);
//     cJSON_AddStringToObject(content, "left_VibInt", tempStr);
//     sprintf(tempStr, "%d", cbdata[9]);
//     cJSON_AddStringToObject(content, "right_VibFreq", tempStr);
//     sprintf(tempStr, "%d", cbdata[10]);
//     cJSON_AddStringToObject(content, "right_VibInt", tempStr);
//     sprintf(tempStr, "%d", cbdata[11]);
//     cJSON_AddStringToObject(content, "left_HR", tempStr);
//     sprintf(tempStr, "%d", cbdata[12]);
//     cJSON_AddStringToObject(content, "left_RR", tempStr);
//     sprintf(tempStr, "%d", cbdata[14]);
//     cJSON_AddStringToObject(content, "right_HR", tempStr);
//     sprintf(tempStr, "%d", cbdata[15]);
//     cJSON_AddStringToObject(content, "right_RR", tempStr);
//     int left_body_state = (Left_Body_State[0] - '0') * 100 + (Left_Body_State[1] - '0') * 10 + (Left_Body_State[2] - '0');
//     printf("left_body_state = %d\n", left_body_state);
//     sprintf(tempStr, "%d", left_body_state);
//     cJSON_AddStringToObject(content, "Left_Body_State", tempStr);
//     int right_body_state = (Right_Body_State[0] - '0') * 100 + (Right_Body_State[1] - '0') * 10 + (Right_Body_State[2] - '0');
//     printf("right_body_state = %d\n", right_body_state);
//     sprintf(tempStr, "%d", right_body_state);
//     cJSON_AddStringToObject(content, "Right_Body_State", tempStr);
//     cJSON_AddStringToObject(content, "BedWet", "0");

//     char source[] = "Alive";
//     cJSON_AddStringToObject(attributes, "source", source);
//     cJSON_AddStringToObject(attributes, "version", "v0.1");
//     get_time(&system_timestamp);
//     ESP_LOGI(TAG1, "The timestamp is %lld \n", system_timestamp);
//     char timestamp[14];
//     sprintf(timestamp, "%lld", system_timestamp);
//     cJSON_AddStringToObject(attributes, "timestamp", timestamp);
//     // md5校验
//     strcat(wait_encrypt_str, "Alive");
//     strcat(wait_encrypt_str, source);
//     strcat(wait_encrypt_str, timestamp);
//     mbedtls_md5_init(&md5_ctx);
//     mbedtls_md5_starts(&md5_ctx);
//     mbedtls_md5_update(&md5_ctx, (unsigned char *)wait_encrypt_str, strlen((char *)wait_encrypt_str));
//     mbedtls_md5_finish(&md5_ctx, decrypt);
//     sprintf(decrypt_cs, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", decrypt[0], decrypt[1], decrypt[2], decrypt[3], decrypt[4], decrypt[5], decrypt[6], decrypt[7], decrypt[8], decrypt[9],
//             decrypt[10], decrypt[11], decrypt[12], decrypt[13], decrypt[14], decrypt[15]);
//     mbedtls_md5_free(&md5_ctx);
//     cJSON_AddStringToObject(attributes, "sign", (char *)decrypt_cs);
//     cJSON_AddStringToObject(attributes, "append", cjson_data.append);
//     char *ptr = cJSON_Print(attributes);
//     // 发布
//     int msg_id = esp_mqtt_client_publish(client, topic, ptr, 0, 0, 0);
//     ESP_LOGI(TAG2, "sent publish successful, msg_id=%d", msg_id);
//     if (ptr != NULL)
//     {
//         cJSON_free(ptr);
//         ptr = NULL;
//     }
//     cJSON_Delete(attributes);
// }

// 将十六进制的字符串转换成二进制字符串
// 第一个参数为十六进制字符串，第二个为存储二进制字符串的数组
void hexToBin(char hexValue, char *binaryArray)
{
    for (int i = 0; i < 8; i++)
    {
        // 使用位运算获取每一位的值
        binaryArray[7 - i] = ((hexValue >> i) & 0x01) ? '1' : '0';
    }
}

// 将二进制数组转换为整数
int BinarrayToInt(char binaryArray[], int length)
{
    unsigned int result = 0;
    for (int i = 0; i < length; i++)
    {
        result = result + pow(2, (length - i - 1)) * binaryArray[i];
    }
    return result;
}
// 消息回复
void Publish_Reply_Message(esp_mqtt_client_handle_t client, char *topic, bool state)
{
    static const char *TAG3 = "Publish_Reply_Message";
    mbedtls_md5_context md5_ctx;
    char wait_encrypt_str[255] = {0};
    unsigned char decrypt[16];
    char decrypt_cs[33];
    cJSON *attributes = cJSON_CreateObject();
    cJSON *content;
    cJSON_AddStringToObject(attributes, "deviceType", "SmartDevice");
    cJSON_AddStringToObject(attributes, "subType", "RDBed");
    cJSON_AddStringToObject(attributes, "deviceMAC", mac_str);
    cJSON_AddStringToObject(attributes, "familyId", "0");
    cJSON_AddStringToObject(attributes, "groupId", "0");
    cJSON_AddStringToObject(attributes, "operate", "reply");
    // content对象
    cJSON_AddItemToObject(attributes, "content", content = cJSON_CreateObject());
    if (state == true)
    {
        cJSON_AddStringToObject(content, "msg", "success");
        cJSON_AddStringToObject(content, "code", "0");
    }
    else
    {
        cJSON_AddStringToObject(content, "msg", "failed");
        cJSON_AddStringToObject(content, "code", "1");
    }
    char source[] = "Alive";
    cJSON_AddStringToObject(attributes, "source", source);
    cJSON_AddStringToObject(attributes, "version", "v0.1");
    get_time(&system_timestamp);
    ESP_LOGI(TAG1, "The timestamp is %lld \n", system_timestamp);
    char timestamp[14];
    sprintf(timestamp, "%lld", system_timestamp);
    cJSON_AddStringToObject(attributes, "timestamp", timestamp);
    // md5校验
    strcat(wait_encrypt_str, "Alive");
    strcat(wait_encrypt_str, source);
    strcat(wait_encrypt_str, timestamp);
    mbedtls_md5_init(&md5_ctx);
    mbedtls_md5_starts(&md5_ctx);
    mbedtls_md5_update(&md5_ctx, (unsigned char *)wait_encrypt_str, strlen((char *)wait_encrypt_str));
    mbedtls_md5_finish(&md5_ctx, decrypt);
    sprintf(decrypt_cs, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", decrypt[0], decrypt[1], decrypt[2], decrypt[3], decrypt[4], decrypt[5], decrypt[6], decrypt[7], decrypt[8], decrypt[9],
            decrypt[10], decrypt[11], decrypt[12], decrypt[13], decrypt[14], decrypt[15]);
    mbedtls_md5_free(&md5_ctx);
    cJSON_AddStringToObject(attributes, "sign", (char *)decrypt_cs);
    cJSON_AddStringToObject(attributes, "append", cjson_data.append);
    char *ptr = cJSON_Print(attributes);
    // 发布
    int msg_id = esp_mqtt_client_publish(client, topic, ptr, 0, 0, 0);
    ESP_LOGI(TAG3, "sent publish successful, msg_id=%d", msg_id);
    if (ptr != NULL)
    {
        cJSON_free(ptr);
        ptr = NULL;
    }
    cJSON_Delete(attributes);
}

// 存储同步策略的各项参数
int Bed_SyncPolicy_Save(myCJson *data)
{
    static const char *TAG = "Bed_SyncPolicy";
    nvs_handle_t my_handle;
    esp_err_t err = nvs_open(Bed_Storage, NVS_READWRITE, &my_handle);
    err = nvs_set_str(my_handle, "Policy_Type", data->sub_type);
    if (err != ESP_OK)
    {
        ESP_LOGE(TAG, "Policy_Type set error!!!");
        return 0;
    }
    if (strcmp(data->sub_type, "onetime") == 0) // 如果策略是 onetime
    {
        // 创建用于存储日期和时间的结构体
        struct tm tm;
        // 拼接日期和时间字符串
        char dateTimeStr[30] = "";
        snprintf(dateTimeStr, sizeof(dateTimeStr), "%s %s", data->sub_date, data->sub_time);
        if (strptime(dateTimeStr, "%Y-%m-%d %H:%M:%S", &tm) == NULL)
        {
            printf("here1\n");
            printf("日期时间格式错误\n");
            return 0;
        }
        printf("dateTimeStr = %s", dateTimeStr);
        // 使用mktime函数将tm结构转换为时间戳
        if (tm.tm_sec < 0 || tm.tm_sec > 59 ||
            tm.tm_min < 0 || tm.tm_min > 59 ||
            tm.tm_hour < 0 || tm.tm_hour > 23 ||
            tm.tm_mon < 0 || tm.tm_mon > 11 ||
            tm.tm_mday < 1 || tm.tm_mday > 31)
        {
            printf("时间设置错误\n");
            return 0; // 任何一个条件不满足，结构体无效
        }
        time_t onetime_timestamp = mktime(&tm) - 28800;
        if (onetime_timestamp < 0)
        {
            printf("here2\n");
            printf("转换时间戳失败\n");
            return 0;
        }
        printf("onetime_timestamp = %d", (int)onetime_timestamp);
        get_time(&system_timestamp);
        if (onetime_timestamp < system_timestamp)
        {
            printf("here3\n");
            printf("时间设置错误\n");
            return 0;
        }
        // 存入BedSyncPolicy结构体中
        Bed_Sync.timestamp = onetime_timestamp;
    }
    else if (strcmp(data->sub_type, "onetimeWeek") == 0) // 如果策略是 onetimeWeek
    {
        int hours, minutes, seconds;
        strcpy(Bed_Sync.week_time, data->sub_time);
        sscanf(Bed_Sync.week_time, "%d:%d:%d", &hours, &minutes, &seconds);
        if (hours < 0 || hours > 23 || minutes < 0 || minutes > 59 || seconds < 0 || seconds > 59)
        {
            printf("时间设置错误\n");
            return 0;
        }

        strcpy(Bed_Sync.week, data->sub_week);
        int weekMask = (int)strtol(Bed_Sync.week, NULL, 16);
        if (weekMask > 127 || weekMask == 0)
        {
            printf("here4\n");
            printf("周询时间设置错误\n");
            return 0;
        }
    }
    else
    {
        printf("here6\n");
        printf("策略错误\n");
        return 0;
    }
    // err = nvs_set_blob(my_handle, "Task_Create", Task_Create, sizeof(Task_Create));
    // 保存设备类型与设备ID
    int count = sizeof(data->sub_deviceType);
    strcpy(Bed_Sync.deviceType, data->sub_deviceType);
    count = sizeof(data->sub_deviceId);
    strcpy(Bed_Sync.deviceId, data->sub_deviceId);
    // 保存操作的命令以及操作标志位数组
    count = sizeof(Bed_SyncPolicy_State);
    err = nvs_set_blob(my_handle, "Bed_SP_State", Bed_SyncPolicy_State, count); // 存储操作标志位数组

    if (Bed_SyncPolicy_State[0] == 1)
    {
        Bed_Sync.bed_key = atoi(data->bed_key);
        // err = nvs_set_str(my_handle, "left_upkey", data->left_upkey);
    }
    if (Bed_SyncPolicy_State[1] == 1)
    {
        Bed_Sync.left_mode = atoi(data->left_mode);
        // err = nvs_set_str(my_handle, "right_upkey", data->right_upkey);
    }
    if (Bed_SyncPolicy_State[2] == 1)
    {
        Bed_Sync.right_mode = atoi(data->right_mode);
        // err = nvs_set_str(my_handle, "left_downkey", data->left_downkey);
    }
    if (Bed_SyncPolicy_State[3] == 1)
    {
        Bed_Sync.left_settemp = atoi(data->left_temp);
        // err = nvs_set_str(my_handle, "right_downkey", data->right_downkey);
    }
    if (Bed_SyncPolicy_State[4] == 1)
    {
        Bed_Sync.right_settemp = atoi(data->right_temp);
        // err = nvs_set_str(my_handle, "right_downkey", data->right_downkey);
    }
    if (Bed_SyncPolicy_State[5] == 1)
    {
        Bed_Sync.left_time = atoi(data->left_time);
        // err = nvs_set_str(my_handle, "right_downkey", data->right_downkey);
    }
    if (Bed_SyncPolicy_State[6] == 1)
    {
        Bed_Sync.right_time = atoi(data->right_time);
        // err = nvs_set_str(my_handle, "right_downkey", data->right_downkey);
    }
    if (Bed_SyncPolicy_State[7] == 1)
    {
        Bed_Sync.LED = atoi(data->LED);
        // err = nvs_set_str(my_handle, "right_downkey", data->right_downkey);
    }
    // 存储策略参数结构体
    count = sizeof(BedSyncPolicy);
    err = nvs_set_blob(my_handle, "Bed_Sync", &Bed_Sync, count);
    if (err != ESP_OK)
    {
        nvs_close(my_handle);
        ESP_LOGE(TAG, "nvs_set_blob error!!!");
        return 0;
    }

    printf("Save state success!!!!\n");
    err = nvs_commit(my_handle);
    if (err != ESP_OK)
    {
        ESP_LOGE(TAG, "nvs_commit error!!!");
        return 0;
    }
    nvs_close(my_handle);
    iterate_through_nvs();
    return 1;
}

// 用于获取床垫控制参数
void GetBedJson_Control_State(myCJson *data, cJSON *item, int type)
{
    if (cJSON_GetObjectItem(item, "bed_key") == NULL)
    {
        printf("rx json have no bed_key!\n");
        if (type == 1)
        {
            Bed_SyncPolicy_State[0] = 0;
        }
        else if (type == 0)
        {
            Bed_Control_State[0] = 0;
        }
    }
    else
    {
        data->bed_key = cJSON_GetObjectItem(item, "bed_key")->valuestring;
        if (type == 1)
        {
            Bed_SyncPolicy_State[0] = 1;
        }
        else if (type == 0)
        {
            Bed_Control_State[0] = 1;
        }
    }
    if (cJSON_GetObjectItem(item, "left_mode") == NULL)
    {
        printf("rx json have no left_mode!\n");
        if (type == 1)
        {
            Bed_SyncPolicy_State[1] = 0;
        }
        else if (type == 0)
        {
            Bed_Control_State[1] = 0;
        }
    }
    else
    {
        data->left_mode = cJSON_GetObjectItem(item, "left_mode")->valuestring;
        if (type == 1)
        {
            Bed_SyncPolicy_State[1] = 1;
        }
        else if (type == 0)
        {
            Bed_Control_State[1] = 1;
        }
    }

    if (cJSON_GetObjectItem(item, "right_mode") == NULL)
    {
        printf("rx json have no right_mode!\n");
        if (type == 1)
        {
            Bed_SyncPolicy_State[2] = 0;
        }
        else if (type == 0)
        {
            Bed_Control_State[2] = 0;
        }
    }
    else
    {
        data->right_mode = cJSON_GetObjectItem(item, "right_mode")->valuestring;
        if (type == 1)
        {
            Bed_SyncPolicy_State[2] = 1;
        }
        else if (type == 0)
        {
            Bed_Control_State[2] = 1;
        }
    }

    if (cJSON_GetObjectItem(item, "left_temp") == NULL)
    {
        printf("rx json have no left_temp!\n");
        if (type == 1)
        {
            Bed_SyncPolicy_State[3] = 0;
        }
        else if (type == 0)
        {
            Bed_Control_State[3] = 0;
        }
    }
    else
    {
        data->left_temp = cJSON_GetObjectItem(item, "left_temp")->valuestring;
        if (type == 1)
        {
            Bed_SyncPolicy_State[3] = 1;
        }
        else if (type == 0)
        {
            Bed_Control_State[3] = 1;
        }
    }

    if (cJSON_GetObjectItem(item, "right_temp") == NULL)
    {
        printf("rx json have no right_temp!\n");
        if (type == 1)
        {
            Bed_SyncPolicy_State[4] = 0;
        }
        else if (type == 0)
        {
            Bed_Control_State[4] = 0;
        }
    }
    else
    {
        data->right_temp = cJSON_GetObjectItem(item, "right_temp")->valuestring;
        if (type == 1)
        {
            Bed_SyncPolicy_State[4] = 1;
        }
        else if (type == 0)
        {
            Bed_Control_State[4] = 1;
        }
    }

    if (cJSON_GetObjectItem(item, "left_time") == NULL)
    {
        printf("rx json have no left_time!\n");
        if (type == 1)
        {
            Bed_SyncPolicy_State[5] = 0;
        }
        else if (type == 0)
        {
            Bed_Control_State[5] = 0;
        }
    }
    else
    {
        data->left_time = cJSON_GetObjectItem(item, "left_time")->valuestring;
        if (type == 1)
        {
            Bed_SyncPolicy_State[5] = 1;
        }
        else if (type == 0)
        {
            Bed_Control_State[5] = 1;
        }
    }

    if (cJSON_GetObjectItem(item, "right_time") == NULL)
    {
        printf("rx json have no right_time!\n");
        if (type == 1)
        {
            Bed_SyncPolicy_State[6] = 0;
        }
        else if (type == 0)
        {
            Bed_Control_State[6] = 0;
        }
    }
    else
    {
        data->right_time = cJSON_GetObjectItem(item, "right_time")->valuestring;
        if (type == 1)
        {
            Bed_SyncPolicy_State[6] = 1;
        }
        else if (type == 0)
        {
            Bed_Control_State[6] = 1;
        }
    }

    if (cJSON_GetObjectItem(item, "LED") == NULL)
    {
        printf("rx json have no LED!\n");
        if (type == 1)
        {
            Bed_SyncPolicy_State[7] = 0;
        }
        else if (type == 0)
        {
            Bed_Control_State[7] = 0;
        }
    }
    else
    {
        data->LED = cJSON_GetObjectItem(item, "LED")->valuestring;
        if (type == 1)
        {
            Bed_SyncPolicy_State[7] = 1;
        }
        else if (type == 0)
        {
            Bed_Control_State[7] = 1;
        }
    }
}
// void GetBedJson_Control_State(myCJson *data, cJSON *item, int type)
// {

//     if (cJSON_GetObjectItem(item, "left_upkey") == NULL)
//     {
//         printf("rx json have no left_upkey!\n");
//         if (type == 1)
//         {
//             Bed_SyncPolicy_State[0] = 0;
//         }
//     }
//     else
//     {
//         data->left_upkey = cJSON_GetObjectItem(item, "left_upkey")->valuestring;
//         if (type == 1)
//         {
//             Bed_SyncPolicy_State[0] = 1;
//         }
//     }

//     if (cJSON_GetObjectItem(item, "right_upkey") == NULL)
//     {
//         printf("rx json have no right_upkey!\n");
//         if (type == 1)
//         {
//             Bed_SyncPolicy_State[1] = 0;
//         }
//     }
//     else
//     {
//         data->right_upkey = cJSON_GetObjectItem(item, "right_upkey")->valuestring;
//         if (type == 1)
//         {
//             Bed_SyncPolicy_State[1] = 1;
//         }
//     }

//     if (cJSON_GetObjectItem(item, "cost") == NULL)
//     {
//         printf("rx json have no cost!\n");
//         if (type == 1)
//         {
//             Bed_SyncPolicy_State[12] = 0;
//         }
//     }
//     else
//     {
//         data->cost = cJSON_GetObjectItem(item, "cost")->valuestring;
//         if (type == 1)
//         {
//             Bed_SyncPolicy_State[12] = 1;
//         }
//     }

//     if (cJSON_GetObjectItem(item, "left_downkey") == NULL)
//     {
//         printf("rx json have no left_downkey!\n");
//         if (type == 1)
//         {
//             Bed_SyncPolicy_State[2] = 0;
//         }
//     }
//     else
//     {
//         data->left_downkey = cJSON_GetObjectItem(item, "left_downkey")->valuestring;
//         if (type == 1)
//         {
//             Bed_SyncPolicy_State[2] = 1;
//         }
//     }

//     if (cJSON_GetObjectItem(item, "right_downkey") == NULL)
//     {
//         printf("rx json have no right_downkey!\n");
//         if (type == 1)
//         {
//             Bed_SyncPolicy_State[3] = 0;
//         }
//     }
//     else
//     {
//         data->right_downkey = cJSON_GetObjectItem(item, "right_downkey")->valuestring;
//         if (type == 1)
//         {
//             Bed_SyncPolicy_State[3] = 1;
//         }
//     }

//     if (cJSON_GetObjectItem(item, "left_uptemp") == NULL)
//     {
//         printf("rx json have no left_uptemp!\n");
//         if (type == 1)
//         {
//             Bed_SyncPolicy_State[4] = 0;
//         }
//     }
//     else
//     {
//         data->left_uptemp = cJSON_GetObjectItem(item, "left_uptemp")->valuestring;
//         if (type == 1)
//         {
//             Bed_SyncPolicy_State[4] = 1;
//         }
//     }

//     if (cJSON_GetObjectItem(item, "right_uptemp") == NULL)
//     {
//         printf("rx json have no right_uptemp!\n");
//         if (type == 1)
//         {
//             Bed_SyncPolicy_State[5] = 0;
//         }
//     }
//     else
//     {
//         data->right_uptemp = cJSON_GetObjectItem(item, "right_uptemp")->valuestring;
//         if (type == 1)
//         {
//             Bed_SyncPolicy_State[5] = 1;
//         }
//     }

//     if (cJSON_GetObjectItem(item, "left_downtemp") == NULL)
//     {
//         printf("rx json have no left_downtemp!\n");
//         if (type == 1)
//         {
//             Bed_SyncPolicy_State[6] = 0;
//         }
//     }
//     else
//     {
//         data->left_downtemp = cJSON_GetObjectItem(item, "left_downtemp")->valuestring;
//         if (type == 1)
//         {
//             Bed_SyncPolicy_State[6] = 1;
//         }
//     }

//     if (cJSON_GetObjectItem(item, "right_downtemp") == NULL)
//     {
//         printf("rx json have no right_downtemp!\n");
//         if (type == 1)
//         {
//             Bed_SyncPolicy_State[7] = 0;
//         }
//     }
//     else
//     {
//         data->right_downtemp = cJSON_GetObjectItem(item, "right_downtemp")->valuestring;
//         if (type == 1)
//         {
//             Bed_SyncPolicy_State[7] = 1;
//         }
//     }

//     if (cJSON_GetObjectItem(item, "left_VibFreq") == NULL)
//     {
//         printf("rx json have no left_VibFreq!\n");
//         if (type == 1)
//         {
//             Bed_SyncPolicy_State[8] = 0;
//         }
//     }
//     else
//     {
//         data->left_VibFreq = cJSON_GetObjectItem(item, "left_VibFreq")->valuestring;
//         if (type == 1)
//         {
//             Bed_SyncPolicy_State[8] = 1;
//         }
//     }

//     if (cJSON_GetObjectItem(item, "left_VibInt") == NULL)
//     {
//         printf("rx json have no left_VibInt!\n");
//         if (type == 1)
//         {
//             Bed_SyncPolicy_State[9] = 0;
//         }
//     }
//     else
//     {
//         data->left_VibInt = cJSON_GetObjectItem(item, "left_VibInt")->valuestring;
//         if (type == 1)
//         {
//             Bed_SyncPolicy_State[9] = 1;
//         }
//     }

//     if (cJSON_GetObjectItem(item, "right_VibFreq") == NULL)
//     {
//         printf("rx json have no right_VibFreq!\n");
//         if (type == 1)
//         {
//             Bed_SyncPolicy_State[10] = 0;
//         }
//     }
//     else
//     {
//         data->right_VibFreq = cJSON_GetObjectItem(item, "right_VibFreq")->valuestring;
//         if (type == 1)
//         {
//             Bed_SyncPolicy_State[10] = 1;
//         }
//     }

//     if (cJSON_GetObjectItem(item, "right_VibInt") == NULL)
//     {
//         printf("rx json have no right_VibInt!\n");
//         if (type == 1)
//         {
//             Bed_SyncPolicy_State[11] = 0;
//         }
//     }
//     else
//     {
//         data->right_VibInt = cJSON_GetObjectItem(item, "right_VibInt")->valuestring;
//         if (type == 1)
//         {
//             Bed_SyncPolicy_State[11] = 1;
//         }
//     }
//     // for (int i = 0; i < 12; i++)
//     // {
//     //     printf("Bed_SyncPolicy_State[%d] = %d\n", i, Bed_SyncPolicy_State[i]);
//     // }
// }
// 状态改变上报任务开启或关闭
int Bed_Change_TaskKey(void)
{
    printf("Bed_Change_TaskKey in!!!\n");
    nvs_handle_t my_handle;
    esp_err_t err = nvs_open(Bed_Storage, NVS_READWRITE, &my_handle);
    size_t count = 0;
    // 读取任务创建状态标志位
    err = nvs_get_i8(my_handle, "BedChange_flag", (int8_t *)&BedChange_flag);
    if (err == ESP_ERR_NVS_NOT_FOUND)
    {
        nvs_set_i8(my_handle, "BedChange_flag", BedChange_flag);
        nvs_commit(my_handle);
    }
    err = nvs_get_i8(my_handle, "BedChange_flag", (int8_t *)&BedChange_flag);
    printf(" BedChange_flag = %d \n", BedChange_flag);
    // 读取任务开关
    count = 0;
    err = nvs_get_str(my_handle, "changeEN", NULL, &count);
    if (err != ESP_OK || count == 0)
    {
        printf("Error (%s) getting size of changeEN or changeEN not found!\n", esp_err_to_name(err));
        nvs_close(my_handle);
        return 0; // 退出函数
    }
    char *changeEN = (char *)malloc(count);
    if (!changeEN)
    {
        printf("Failed to allocate memory for changeEN\n");
        nvs_close(my_handle);
        return 0; // 退出函数
    }
    err = nvs_get_str(my_handle, "changeEN", changeEN, &count);
    printf("changeEN = %s\n", changeEN);
    if (err != ESP_OK)
    {
        printf("Error (%s) reading changeEN!\n", esp_err_to_name(err));
        free(changeEN);
        nvs_close(my_handle);
        return 0; // 退出函数
    }
    //  根据报文，开启或关闭任务
    if (strcmp(changeEN, "enable") == 0)
    {
        printf("changeEN is enable\n");
        free(changeEN);
        if (BedChange_flag == 0)
        {
            printf("创建状态改变任务\n");
            BedChange_flag = 1;
            xTaskCreate(bed_change_task, "bed_change_task", 4096, NULL, 20, &BedChangeHandle);
            if (BedChange_flag == 0)
            {
                return 0;
            }
        }
        else
        {
            if (BedChangeHandle == NULL)
            {
                xTaskCreate(bed_change_task, "bed_change_task", 4096, NULL, 20, &BedChangeHandle);
            }
            printf("状态改变任务已被创建过\n");
        }
    }
    else if (strcmp(changeEN, "disable") == 0)
    {
        printf("changeEN is disable\n");
        free(changeEN);
        if (BedChange_flag == 1)
        {
            printf("删除状态改变任务\n");
            vTaskDelete(BedChangeHandle);
            BedChange_flag = 0;
        }
        else
        {
            printf("状态改变任务未被创建\n");
        }
    }
    err = nvs_set_i8(my_handle, "BedChange_flag", BedChange_flag);
    err = nvs_commit(my_handle);
    nvs_close(my_handle);
    return 1;
}
// 同步策略任务开启或关闭
int Bed_SyncPolicy_TaskKey(void)
{
    printf("Bed_SyncPolicy_TaskKey in!!!\n");
    nvs_handle_t my_handle;
    esp_err_t err = nvs_open(Bed_Storage, NVS_READWRITE, &my_handle);
    // 读取策略任务创建状态标志位
    size_t count = 0;
    err = nvs_get_i8(my_handle, "BedSyncOnce_flag", (int8_t *)&BedSyncOnce_flag);
    if (err == ESP_ERR_NVS_NOT_FOUND)
    {
        nvs_set_i8(my_handle, "BedSyncOnce_flag", BedSyncOnce_flag);
        nvs_commit(my_handle);
    }
    err = nvs_get_i8(my_handle, "BedSyncWeek_flag", (int8_t *)&BedSyncWeek_flag);
    if (err == ESP_ERR_NVS_NOT_FOUND)
    {
        nvs_set_i8(my_handle, "BedSyncWeek_flag", BedSyncWeek_flag);
        nvs_commit(my_handle);
    }

    err = nvs_get_i8(my_handle, "BedSyncOnce_flag", (int8_t *)&BedSyncOnce_flag);
    err = nvs_get_i8(my_handle, "BedSyncWeek_flag", (int8_t *)&BedSyncWeek_flag);
    printf(" BedSyncOnce_flag = %d, BedSyncWeek_flag = %d\n", BedSyncOnce_flag, BedSyncWeek_flag);
    // 读取策略开关
    count = 0;
    err = nvs_get_str(my_handle, "onetimeEn", NULL, &count);
    if (err == ESP_ERR_NVS_NOT_FOUND)
    {
        printf("Error (%s) getting size of onetimeEn or onetimeEn not found!\n", esp_err_to_name(err));
        nvs_set_str(my_handle, "onetimeEn", "disable");
        nvs_commit(my_handle);
    }
    err = nvs_get_str(my_handle, "onetimeEn", NULL, &count);
    char *onetimeEn = (char *)malloc(count);
    err = nvs_get_str(my_handle, "onetimeEn", onetimeEn, &count);
    printf("onetimeEn = %s\n", onetimeEn);
    count = 0;
    err = nvs_get_str(my_handle, "onetimeWeekEn", NULL, &count);
    if (err == ESP_ERR_NVS_NOT_FOUND)
    {
        printf("Error (%s) getting size of onetimeWeekEn or onetimeWeekEn not found!\n", esp_err_to_name(err));
        nvs_set_str(my_handle, "onetimeWeekEn", "disable");
        nvs_commit(my_handle);
    }
    err = nvs_get_str(my_handle, "onetimeWeekEn", NULL, &count);
    char *onetimeWeekEn = (char *)malloc(count);
    err = nvs_get_str(my_handle, "onetimeWeekEn", onetimeWeekEn, &count);
    printf("onetimeWeekEn = %s\n", onetimeWeekEn);
    // 读取一次性定时策略时间
    count = 0;
    nvs_get_blob(my_handle, "Bed_Sync", NULL, &count);
    BedSyncPolicy Bed_Key_Sync;
    nvs_get_blob(my_handle, "Bed_Sync", &Bed_Key_Sync, &count);
    //  根据报文，开启或关闭策略任务
    if (strcmp(onetimeEn, "enable") == 0)
    {
        printf("onetimeEn is enable\n");
        free(onetimeEn);
        // 判断策略时间是否过时
        get_time(&system_timestamp);
        if ((system_timestamp - Bed_Key_Sync.timestamp > 4) && (system_timestamp > Bed_Key_Sync.timestamp))
        {
            printf("Missing the scheduled time\n");
            nvs_close(my_handle);
            return 0; // 退出函数
        }
        if (BedSyncOnce_flag == 0)
        {
            printf("创建同步一次策略任务\n");
            BedSyncOnce_flag = 1;
            xTaskCreate(Bed_SyncPolicy_OneTime_Task, "Bed_SyncPolicy_OneTime_Task", 6144, NULL, 21, &BedSyncOnceHandle);
            if (BedSyncOnce_flag == 0)
            {
                return 0;
            }
        }
        else
        {
            if (BedSyncOnceHandle == NULL)
            {
                xTaskCreate(Bed_SyncPolicy_OneTime_Task, "Bed_SyncPolicy_OneTime_Task", 6144, NULL, 21, &BedSyncOnceHandle);
            }
            printf("同步一次策略任务已被创建过\n");
        }
    }
    else if (strcmp(onetimeEn, "disable") == 0)
    {
        printf("onetimeWeekEn is disable\n");
        if (BedSyncOnce_flag == 1)
        {
            printf("删除同步一次策略任务\n");
            vTaskDelete(BedSyncOnceHandle);
            BedSyncOnce_flag = 0;
        }
        else
        {
            printf("同步一次策略任务未被创建\n");
        }
    }

    if (strcmp(onetimeWeekEn, "enable") == 0)
    {
        printf("onetimeWeekEn is enable\n");
        free(onetimeWeekEn);
        if (BedSyncWeek_flag == 0)
        {
            printf("创建同步周期策略任务\n");
            xTaskCreate(Bed_SyncPolicy_OneTimeWeek_Task, "Bed_SyncPolicy_OneTimeWeek_Task", 4096, NULL, 21, &BedSyncWeekHandle);
            BedSyncWeek_flag = 1;
        }
        else
        {
            if (BedSyncWeekHandle == NULL)
            {
                xTaskCreate(Bed_SyncPolicy_OneTimeWeek_Task, "Bed_SyncPolicy_OneTimeWeek_Task", 4096, NULL, 21, &BedSyncWeekHandle);
            }
            printf("同步周期策略任务已被创建过\n");
        }
    }
    else if (strcmp(onetimeWeekEn, "disable") == 0)
    {
        if (BedSyncWeek_flag == 1)
        {
            printf("删除同步周期策略任务\n");
            vTaskDelete(BedSyncWeekHandle);
            BedSyncWeek_flag = 0;
        }
        else
        {
            printf("同步周期策略任务未被创建\n");
        }
    }
    // 读取
    //  更新标志位
    err = nvs_set_i8(my_handle, "BedSyncOnce_flag", BedSyncOnce_flag);
    err = nvs_set_i8(my_handle, "BedSyncWeek_flag", BedSyncWeek_flag);
    err = nvs_commit(my_handle);
    nvs_close(my_handle);
    return 1;
}

// 一次性策略定时任务
void Bed_SyncPolicy_OneTime_Task(void *arg)
{
    printf("OneTime_Task_in!!!\n");
    nvs_handle_t my_handle;
    size_t required_size = 0;
    BedSyncPolicy Bed_Start_Sync;
    // 任务创建标志位置1
    esp_err_t err = nvs_open(Bed_Storage, NVS_READWRITE, &my_handle);
    BedSyncOnce_flag = 1;
    nvs_set_i8(my_handle, "BedSyncOnce_flag", BedSyncOnce_flag);
    err = nvs_commit(my_handle);
    nvs_close(my_handle);

    while (1)
    {
        esp_err_t err = nvs_open(Bed_Storage, NVS_READWRITE, &my_handle);
        if (err != ESP_OK)
        {
            printf("Error (%s) opening NVS handle!\n", esp_err_to_name(err));
            nvs_close(my_handle);
        }
        // 获取控制标志位数组
        required_size = 0;
        nvs_get_blob(my_handle, "Bed_SP_State", NULL, &required_size);
        char Bed_SP_State[required_size]; // 0：bed_key，1~2左右模式，3~4左右温度，5~6左右时间，7指示灯
        nvs_get_blob(my_handle, "Bed_SP_State", Bed_SP_State, &required_size);
        // for (size_t i = 0; i < required_size; i++)
        // {
        //     printf("Bed_SP_State[%d] = %d\n", i, Bed_SP_State[i]);
        // }
        // 获取策略控制参数
        required_size = 0;
        err = nvs_get_blob(my_handle, "Bed_Sync", NULL, &required_size);
        if (err != ESP_OK || required_size != sizeof(BedSyncPolicy))
        {
            nvs_close(my_handle);
            printf("get_Bed_Sync_Error!!!\n");
        }
        else
        {
            err = nvs_get_blob(my_handle, "Bed_Sync", &Bed_Start_Sync, &required_size);
            if (err != ESP_OK)
            {
                nvs_close(my_handle);
                printf("get_Bed_Sync_Error!!!\n");
            }
        }
        nvs_close(my_handle);

        get_time(&system_timestamp);
        printf("system_timestamp = %lld,Bed_Start_Sync.timestamp = %lld\n", system_timestamp, Bed_Start_Sync.timestamp);
        if (system_timestamp - 3 < Bed_Start_Sync.timestamp && Bed_Start_Sync.timestamp < system_timestamp + 3) // 如果到达执行时间
        {
            if (Bed_SP_State[0] == 1)
            {
                Bed_Write.bed_key = Bed_Start_Sync.bed_key;
            }
            if (Bed_SP_State[1] == 1)
            {
                Bed_Write.left_mode = Bed_Start_Sync.left_mode;
            }
            if (Bed_SP_State[2] == 1)
            {
                Bed_Write.right_mode = Bed_Start_Sync.right_mode;
            }
            if (Bed_SP_State[3] == 1)
            {
                Bed_Write.left_settemp = Bed_Start_Sync.left_settemp;
            }
            if (Bed_SP_State[4] == 1)
            {
                Bed_Write.right_settemp = Bed_Start_Sync.right_settemp;
            }
            if (Bed_SP_State[5] == 1)
            {
                Bed_Write.left_time = Bed_Start_Sync.left_time;
            }
            if (Bed_SP_State[6] == 1)
            {
                Bed_Write.right_time = Bed_Start_Sync.right_time;
            }
            if (Bed_SP_State[7] == 1)
            {
                Bed_Write.LED = Bed_Start_Sync.LED;
            }
            memcpy(Bed_Control_State, Bed_SP_State, sizeof(Bed_SP_State)); // 赋值控制参数标志位
            printf("到达指定时间\n");
            policy_tx = 1; // 策略控制标志位置一
            // 任务创建标志位置0
            err = nvs_open(Bed_Storage, NVS_READWRITE, &my_handle);
            BedSyncOnce_flag = 0;
            nvs_set_i8(my_handle, "BedSyncOnce_flag", BedSyncOnce_flag);
            err = nvs_commit(my_handle);
            nvs_close(my_handle);
            printf("Mission accomplished\n");

            vTaskDelete(NULL);
        }
        else if ((system_timestamp - Bed_Start_Sync.timestamp > 4) && (system_timestamp > Bed_Start_Sync.timestamp))
        {
            printf("miss time!!!\n");
            // 任务创建标志位置0
            err = nvs_open(Bed_Storage, NVS_READWRITE, &my_handle);
            BedSyncOnce_flag = 0;
            nvs_set_i8(my_handle, "BedSyncOnce_flag", BedSyncOnce_flag);
            err = nvs_commit(my_handle);
            nvs_close(my_handle);
            printf("Mission Falied\n");
            Publish_Reply_Message(my_client, g_publish_topic, false);
            vTaskDelete(NULL);
        }
        else
        {
            printf("Time is not yet up.\n");
        }
        vTaskDelay(2000 / portTICK_PERIOD_MS);
    }
}
// 周轮询定时任务
void Bed_SyncPolicy_OneTimeWeek_Task(void *arg)
{

    printf("OneTimeWeek_Task_in!!!\n");
    // char timeStr[10]; // HH:MM:SS 需要8个字符 + 1个null终止符
    struct tm *tm;
    nvs_handle_t my_handle;
    esp_err_t err;
    BedSyncPolicy Bed_Start_Sync;
    int hours, minutes, seconds;
    // 任务创建标志位置1
    err = nvs_open(Bed_Storage, NVS_READWRITE, &my_handle);
    BedSyncWeek_flag = 1;
    nvs_set_i8(my_handle, "BedSyncWeek_flag", BedSyncWeek_flag);
    err = nvs_commit(my_handle);
    nvs_close(my_handle);

    while (1)
    {
        err = nvs_open(Bed_Storage, NVS_READWRITE, &my_handle);
        size_t required_size = 0;
        if (err != ESP_OK)
        {
            printf("Error (%s) opening NVS handle!\n", esp_err_to_name(err));
            nvs_close(my_handle);
        }
        // 获取控制标志位数组
        required_size = 0;
        nvs_get_blob(my_handle, "Bed_SP_State", NULL, &required_size);
        char Bed_SP_State[required_size];

        nvs_get_blob(my_handle, "Bed_SP_State", Bed_SP_State, &required_size);
        // 获取控制参数
        required_size = 0;
        err = nvs_get_blob(my_handle, "Bed_Sync", NULL, &required_size);
        if (err != ESP_OK || required_size != sizeof(BedSyncPolicy))
        {
            nvs_close(my_handle);
            printf("get_Bed_Sync_Error!!!\n");
        }
        else
        {
            err = nvs_get_blob(my_handle, "Bed_Sync", &Bed_Start_Sync, &required_size);
            if (err != ESP_OK)
            {
                nvs_close(my_handle);
                printf("get_Bed_Sync_Error!!!\n");
            }
        }
        nvs_close(my_handle);
        required_size = 0;
        sscanf(Bed_Start_Sync.week_time, "%d:%d:%d", &hours, &minutes, &seconds);

        get_time(&system_timestamp);
        time_t timestamp = (time_t)system_timestamp;
        tm = localtime(&timestamp);
        tm->tm_hour += 8;
        int weekMask = (int)strtol(Bed_Start_Sync.week, NULL, 16);
        // snprintf(timeStr, sizeof(timeStr), "%02d:%02d:%02d", tm->tm_hour, tm->tm_min, tm->tm_sec);
        printf("tm_hour = %d,tm_min = %d,tm_sec = %d\n", tm->tm_hour, tm->tm_min, tm->tm_sec);
        printf("hours = %d,minutes = %d,seconds = %d\n", hours, minutes, seconds);
        if ((weekMask & (1 << tm->tm_wday)) != 0)
        {
            printf("任务日，今天是星期%d\n", tm->tm_wday);
            if (tm->tm_hour == hours && tm->tm_min == minutes && (seconds > (tm->tm_sec - 2) && seconds < (tm->tm_sec + 2))) // 到达指定时间
            {
                if (Bed_SP_State[0] == 1)
                {
                    Bed_Write.bed_key = Bed_Start_Sync.bed_key;
                }
                if (Bed_SP_State[1] == 1)
                {
                    Bed_Write.left_mode = Bed_Start_Sync.left_mode;
                }
                if (Bed_SP_State[2] == 1)
                {
                    Bed_Write.right_mode = Bed_Start_Sync.right_mode;
                }
                if (Bed_SP_State[3] == 1)
                {
                    Bed_Write.left_settemp = Bed_Start_Sync.left_settemp;
                }
                if (Bed_SP_State[4] == 1)
                {
                    Bed_Write.right_settemp = Bed_Start_Sync.right_settemp;
                }
                if (Bed_SP_State[5] == 1)
                {
                    Bed_Write.left_time = Bed_Start_Sync.left_time;
                }
                if (Bed_SP_State[6] == 1)
                {
                    Bed_Write.right_time = Bed_Start_Sync.right_time;
                }
                if (Bed_SP_State[7] == 1)
                {
                    Bed_Write.LED = Bed_Start_Sync.LED;
                }
                memcpy(Bed_Control_State, Bed_SP_State, sizeof(Bed_SP_State)); // 赋值控制参数标志位
                printf("到达指定时间\n");
                policy_tx = 1; // 策略控制标志位置一
                // // 任务创建标志位置0
                // err = nvs_open(Bed_Storage, NVS_READWRITE, &my_handle);
                // BedSyncWeek_flag = 0;
                // nvs_set_i8(my_handle, "BedSyncWeek_flag", BedSyncWeek_flag);
                // err = nvs_commit(my_handle);
                // nvs_close(my_handle);
                printf("Mission accomplished\n");
                // vTaskDelete(NULL);
                vTaskDelay(5000 / portTICK_PERIOD_MS);
            }
        }
        else
        {
            printf("非任务日\n");
        }
        vTaskDelay(2000 / portTICK_PERIOD_MS);
    }
}
// NVS迭代器，打印NVS命名空间中的所有键与对应值
void iterate_through_nvs(void)
{
    nvs_handle_t my_handle;
    esp_err_t err = nvs_open(Bed_Storage, NVS_READWRITE, &my_handle);
    if (err != ESP_OK)
    {
        printf("Error (%s) opening NVS handle!\n", esp_err_to_name(err));
    }
    else
    {
        nvs_iterator_t it = NULL;
        err = nvs_entry_find("nvs", Bed_Storage, NVS_TYPE_ANY, &it);

        // 确保nvs_entry_find成功
        if (err != ESP_OK)
        {
            printf("Error (%s) finding first NVS entry!\n", esp_err_to_name(err));
            nvs_close(my_handle);
            return;
        }

        while (it != NULL)
        {
            nvs_entry_info_t info;
            err = nvs_entry_info(it, &info); // 检查这步是否成功
            if (err != ESP_OK)
            {
                printf("Error (%s) getting NVS entry info!\n", esp_err_to_name(err));
                break;
            }

            printf("key '%s', type '%02x' \n", info.key, info.type);
            // 根据类型读取并打印值
            switch (info.type)
            {
            case NVS_TYPE_I32:
            {
                int32_t value;
                nvs_get_i32(my_handle, info.key, &value);
                printf("Value (int32): %ld\n", (long)value);
                break;
            }
            case NVS_TYPE_STR:
            {
                size_t required_size;
                nvs_get_str(my_handle, info.key, NULL, &required_size);
                char *value = malloc(required_size);
                nvs_get_str(my_handle, info.key, value, &required_size);
                printf("Value (string):%s: %s\n", info.key, value);
                free(value);
                break;
            }
            case NVS_TYPE_BLOB:
            {
                size_t required_size;
                nvs_get_blob(my_handle, info.key, NULL, &required_size);
                char *value = malloc(required_size);
                nvs_get_blob(my_handle, info.key, value, &required_size);
                printf("Value (blob): %s\n", value);

                for (size_t i = 0; i < (required_size); i++)
                {
                    printf("%s[%d] = %d\n", info.key, i, value[i]);
                }
                free(value);
                break;
            }
            // 添加其他类型的处理...
            default:
                printf("Unsupported type\n");
            }

            // 正确更新迭代器
            err = nvs_entry_next(&it);
            if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND)
            {
                printf("Error (%s) nvs_entry_next!\n", esp_err_to_name(err));
                break;
            }
            if (it == NULL)
            {
                break; // 如果没有更多条目，则退出循环
            }
        }
        printf("iterate ok!!!\n");
        if (it != NULL)
        {
            nvs_release_iterator(it); // 确保最后释放迭代器
        }
    }
    nvs_close(my_handle);
}

void Bed_Nvs_Erase_All(void)
{
    nvs_handle_t my_handle;
    esp_err_t err = nvs_open(Bed_Storage, NVS_READWRITE, &my_handle);
    if (err != ESP_OK)
    {
        printf("Error (%s) opening NVS handle!\n", esp_err_to_name(err));
        return; // 退出函数
    }
    err = nvs_erase_all(my_handle);
    if (err != ESP_OK)
    {
        printf("Error (%s) erasing NVS!\n", esp_err_to_name(err));
    }
    else
    {
        printf("NVS namespace erased\n");
    }

    nvs_commit(my_handle);
    nvs_close(my_handle);
}

// 床垫状态改变上报任务
void bed_change_task(void *arg)
{
    size_t count = 0;
    static const char *CHANGE_TASK_TAG = "BED_CHANGE_TASK";
    BedControlTime bed_time;
    nvs_handle_t my_handle;
    static uint8_t last_bed_state[23] = {0};
    static uint8_t bed_state[23] = {0};
    char hr_rr_body[6] = {0}; // 用来记录心率、呼吸、体动数值是否相等,0~2:左，3~5：右
    esp_err_t err;
    int left_time;
    int right_time;
    // 任务创建标志位置1
    err = nvs_open(Bed_Storage, NVS_READWRITE, &my_handle);
    BedChange_flag = 1;
    nvs_set_i8(my_handle, "BedChange_flag", BedChange_flag);
    err = nvs_commit(my_handle);
    nvs_close(my_handle);

    while (1)
    {
        if (bed_tx == 0)
        {
            bed_tx = 2;
        }
        printf("等待bed_rx_task的通知\n");
        ulTaskNotifyTake(pdTRUE, (TickType_t)150);
        printf("接收到bed_rx_task通知");
        printf("bed_tx = %d,bed_rx = %d", bed_tx, bed_rx);
        if (bed_rx == 0)
        {
            printf("已获取床最新状态\n");

            err = nvs_open(Bed_Storage, NVS_READWRITE, &my_handle);
            if (err != ESP_OK)
            {
                ESP_LOGE(CHANGE_TASK_TAG, "bed_state set error!!!");
            }
            //  读取床状态
            count = 0;
            err = nvs_get_blob(my_handle, "bed_state", NULL, &count);
            printf("count = %d\n", count);
            err = nvs_get_blob(my_handle, "bed_state", &bed_state, &count);
            // 读取床定时状态
            count = sizeof(BedControlTime);
            err = nvs_get_blob(my_handle, "Bed_Time", &bed_time, &count);
            nvs_close(my_handle);
            if (err != ESP_OK)
            {
                printf("Error (%s) erasing NVS!\n", esp_err_to_name(err));
                bed_time.lefttime_set = 0;
                bed_time.righttime_set = 0;
            }
            printf("lefttime_set = %d,righttime_set = %d\n", bed_time.lefttime_set, bed_time.righttime_set);
            if (bed_time.lefttime_set == 1) // 有左区定时
            {
                bed_state[5] = bed_time.left_endtime - bed_time.left_starttime;
                printf("bed_state[5] = %d\n", bed_state[5]);
            }
            if (bed_time.righttime_set == 1) // 有左区定时
            {
                bed_state[12] = bed_time.right_endtime - bed_time.right_starttime;
                printf("bed_state[12] = %d\n", bed_state[12]);
            }

            // 与上次的状态进行比较
            count = 23;
            if (memcmp(last_bed_state, bed_state, 23 * sizeof(uint8_t)) == 0)
            {
                printf("数据相同,无需上报。\n");
            }
            else
            {
                printf("数据更新\n");
                // 判断左右的三种特别参数是否相等
                if (last_bed_state[8] == bed_state[8])
                {
                    printf("左床心率相同\n");
                    hr_rr_body[0] = 1;
                }
                else
                {
                    printf("左床心率不同\n");
                    hr_rr_body[0] = 0;
                }
                if (last_bed_state[9] == bed_state[9])
                {
                    printf("左床呼吸相同\n");
                    hr_rr_body[1] = 1;
                }
                else
                {
                    printf("左床呼吸不同\n");
                    hr_rr_body[1] = 0;
                }
                if (last_bed_state[10] == bed_state[10])
                {
                    printf("左床体动相同\n");
                    hr_rr_body[2] = 1;
                }
                else
                {
                    printf("左床体动不同\n");
                    hr_rr_body[2] = 0;
                }
                if (last_bed_state[15] == bed_state[15])
                {
                    printf("右床心率相同\n");
                    hr_rr_body[3] = 1;
                }
                else
                {
                    printf("右床心率不同\n");
                    hr_rr_body[3] = 0;
                }
                if (last_bed_state[16] == bed_state[16])
                {
                    printf("右床呼吸相同\n");
                    hr_rr_body[4] = 1;
                }
                else
                {
                    printf("右床呼吸不同\n");
                    hr_rr_body[4] = 0;
                }
                if (last_bed_state[17] == bed_state[17])
                {
                    printf("右床体动相同\n");
                    hr_rr_body[5] = 1;
                }
                else
                {
                    printf("右床体动不同\n");
                    hr_rr_body[5] = 0;
                }
                printf("开始上报\n");
                Publish_Bed_State(my_client, g_publish_topic, bed_state, hr_rr_body);
                memcpy(last_bed_state, bed_state, count);
            }
        }
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
}

void bed_rx_task(void *arg)
{
    static const char *RX_TASK_TAG = "BED_RX_TASK";
    const int RX_BUF_SIZE = 1024;
    // esp_log_level_set(RX_TASK_TAG, ESP_LOG_INFO);
    uint8_t data[RX_BUF_SIZE + 1]; // 使用栈内存代替malloc
    while (1)
    {
        if (xSemaphore != NULL)
        {
            if (xSemaphoreTake(xSemaphore, (TickType_t)10) == pdTRUE)
            {
                const int rxBytes = uart_read_bytes(BED_UART_NUM, data, RX_BUF_SIZE, 100);
                if (rxBytes > 0)
                {
                    ESP_LOG_BUFFER_HEXDUMP(RX_TASK_TAG, data, rxBytes, ESP_LOG_INFO); // 直接打印十六进制数据
                    bed_rxdata_parse(data, rxBytes);
                    if (BedChangeHandle != NULL)
                    {
                        printf("向bed_change_task发送通知\n");
                        xTaskNotifyGive(BedChangeHandle);
                    }
                    if (xSemaphore != NULL) // 释放信号量
                    {
                        printf("接收完成,释放信号量\n");
                        xSemaphoreGive(xSemaphore);
                    }
                    else
                    {
                        printf("无需重复释放\n");
                    }
                }
                else
                {
                    if (xSemaphore != NULL)
                    {
                        xSemaphoreGive(xSemaphore);
                    }
                    else
                    {
                        printf("无需重复释放\n");
                    }
                }
            }
        }
        else
        {
            xSemaphore = xSemaphoreCreateMutex();
            printf("重新创建\n");
        }
        vTaskDelay(1 / portTICK_PERIOD_MS); // 为了避免持续占用CPU，适当地加入延时
    }
}

void bed_rxdata_parse(uint8_t *data, int rxBytes)
{
    size_t count = 0;
    BedControlTime bed_time;
    static const char *TAG = "rxdata_parse";
    nvs_handle_t my_handle;
    unsigned int checksum = 0; // 记载自己计算的校验和
    esp_err_t err;
    static char hr_rr_body[6] = {0};
    static int first_read = 1;
    for (size_t i = 1; i < (rxBytes - 1); i++)
    {
        checksum += data[i];
    }
    // 只保留累加和的低八位
    checksum &= 0xFF;
    // 检查数据是否准确
    if (data[0] != 0xAA || data[rxBytes - 1] != (uint8_t)checksum)
    {
        printf("数据错误\n");
        printf("checksum:%02x,data[rxBytes - 1]:%02x", (uint8_t)checksum, data[rxBytes - 1]);
    }
    else
    {
        // 取出时间数据
        count = 0;
        err = nvs_open(Bed_Storage, NVS_READWRITE, &my_handle);
        printf("数据校验成功\n");
        printf("rxBytes = %d\n", rxBytes);
        if (bed_rx == 1)
        {
            bed_rx = 0;
            if (data[2] == 0x07)
            {
                printf("收到设备状态命令\n");
                Bed_Read.bed_key = data[3];
                Bed_Read.left_mode = data[4];
                Bed_Read.left_time = data[5];
                Bed_Read.left_settemp = data[6];
                Bed_Read.left_nowtemp = data[7];
                Bed_Read.left_HR = data[8];
                Bed_Read.left_RR = data[9];
                hexToBin(data[10], Left_Body_State); // 左床体动
                if (Left_Body_State[0] == 1)
                {
                    Bed_Read.left_isonbed = 1;
                }
                else
                {
                    Bed_Read.left_isonbed = 0;
                }
                if (Left_Body_State[1] == 1)
                {
                    Bed_Read.left_Motion = 1;
                }
                else
                {
                    Bed_Read.left_Motion = 0;
                }
                Bed_Read.right_mode = data[11];
                Bed_Read.right_time = data[12];
                Bed_Read.right_settemp = data[13];
                Bed_Read.right_nowtemp = data[14];
                Bed_Read.right_HR = data[15];
                Bed_Read.right_RR = data[16];
                hexToBin(data[17], Right_Body_State); // 右床体动
                if (Right_Body_State[0] == 1)
                {
                    Bed_Read.right_isonbed = 1;
                }
                else
                {
                    Bed_Read.right_isonbed = 0;
                }
                if (Right_Body_State[1] == 1)
                {
                    Bed_Read.right_Motion = 1;
                }
                else
                {
                    Bed_Read.right_Motion = 0;
                }
                Bed_Read.LED = data[18];
                if (first_read == 1)
                {
                    first_read = 0;
                    printf("第一次读状态指令\n");
                    // 赋值给Bed_Write
                    Bed_Write.bed_key = Bed_Read.bed_key;
                    Bed_Write.left_settemp = Bed_Read.right_settemp;
                    Bed_Write.right_settemp = Bed_Read.right_settemp;
                    Bed_Write.left_mode = Bed_Read.left_mode;
                    Bed_Write.right_mode = Bed_Read.right_mode;
                    Bed_Write.LED = Bed_Read.LED;

                    err = nvs_open(Bed_Storage, NVS_READWRITE, &my_handle);
                    err = nvs_set_blob(my_handle, "Bed_Write", &Bed_Write, sizeof(BedSpread));
                    if (err != ESP_OK)
                    {
                        printf("存储开关状态失败\n");
                    }
                    err = nvs_commit(my_handle);
                    nvs_close(my_handle);
                }
                printf("开始存储设备状态\n");
                err = nvs_open(Bed_Storage, NVS_READWRITE, &my_handle);
                if (err != ESP_OK)
                {
                    ESP_LOGE(TAG, "bed_state set error!!!");
                }

                err = nvs_set_blob(my_handle, "bed_state", data, rxBytes);
                err = nvs_set_blob(my_handle, "Bed_Read", &Bed_Read, sizeof(BedSpread));
                nvs_commit(my_handle);
                nvs_close(my_handle);
                printf("设备状态存储成功\n");
                // 判断命令来自哪里
                if (mqtt_read == 1) // 如果命令来自MQTT主动查询
                {
                    mqtt_read = 0; // 主动查询标志位清零
                    printf("主动查询，需要上报\n");
                    // 回复报文
                    Publish_Bed_State(my_client, g_publish_topic, data, hr_rr_body);
                }
            }
        }
        else
        {
            if ((data[1] == 0x03) && (data[2] == 0x60) && (data[3] == 0x01))
            {

                printf("收到重置WIFI指令\n");
                err = nvs_open(Wifi_Storage, NVS_READWRITE, &my_handle);
                err = nvs_erase_key(my_handle, "wifi_ssid");
                if (err != ESP_OK)
                {
                    ESP_LOGE(TAG, "Delete WiFi_SSID FAIL:%s!\n", esp_err_to_name(err));
                }
                err = nvs_erase_key(my_handle, "wifi_password");
                if (err != ESP_OK)
                {
                    ESP_LOGE(TAG, "Delete WiFi_PASSWORD FAIL:%s!\n", esp_err_to_name(err));
                }
                nvs_commit(my_handle);
                nvs_close(my_handle);
                printf("WIFI配置删除成功\n");
                esp_restart();
            }
            else if ((data[1] == 0x03) && (data[2] == 0x60) && (data[3] == 0x03))
            {
                printf("接收到查询WIFI版本号命令\n");
                while (bed_tx != 0)
                {
                    vTaskDelay(5 / portTICK_PERIOD_MS);
                }
                bed_tx = 9;
                while (bed_tx != 0)
                {
                    vTaskDelay(5 / portTICK_PERIOD_MS); // 为了避免持续占用CPU，适当地加入延时
                }
            }
            else if ((data[1] == 0x03) && (data[2] == 0x60) && (data[3] == 0x04))
            {
                printf("接收到进入WIFI产测命令\n");
                // 产测标志位置一
                bed_test = 1;
                // 存储标志位
                err = nvs_open(Wifi_Storage, NVS_READWRITE, &my_handle);
                err = nvs_set_i64(my_handle, "bed_test", bed_test);
                nvs_commit(my_handle);
                nvs_close(my_handle);
                printf("进入产测,开始重启");
                esp_restart();
            }
        }
    }
}

void bed_control_task(void *arg)
{
    // int policy_ttx; // 用来存放策略控制标志位
    static const char *TX_TASK_TAG = "BED_TX_TASK";
    nvs_handle_t my_handle;
    char write_cmd[10] = {0xAA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; // 写操作指令
    int tx_len = 0;
    bed_tx = 5;
    printf("模组已重置\n");
    while (1)
    {
        // 获取策略控制标志位
        // nvs_open(Bed_Storage, NVS_READWRITE, &my_handle);
        // nvs_get_i64(my_handle, "policy_tx", policy_ttx);
        // nvs_close(my_handle);
        if (policy_tx == 1)
        {
            vTaskDelay(100); // 为了避免持续占用CPU，适当地加入延时
            while (bed_tx != 0)
            {
                vTaskDelay(5 / portTICK_PERIOD_MS);
            }
            bed_tx = 1;
            policy_tx = 0;
            printf("有策略控制\n");
        }
        if (bed_tx == 1)
        {
            printf("开始控制\n");
            // 获取串口信号量
            printf("开始获取信号量\n");
            if (xSemaphore != NULL)
            {
                printf("xSemaphore != NULL\n");
                if (xSemaphoreTake(xSemaphore, portMAX_DELAY) == pdTRUE)
                {
                    bed_tx = 0; // 控制标志位置零
                    printf("获取信号量成功\n");
                    if (Bed_Control_State[0] == 1)
                    {
                        printf("开关\n");
                        tx_len = build_bed_cmd(write_cmd, 0);
                        printf("tx_len = %d\n", tx_len);
                        ESP_LOG_BUFFER_HEXDUMP(TX_TASK_TAG, write_cmd, tx_len, ESP_LOG_INFO); // 直接打印十六进制数据
                        BED_send(BED_UART_NUM, write_cmd, tx_len);
                        vTaskDelay(5 / portTICK_PERIOD_MS);
                    }
                    if (Bed_Control_State[1] == 1)
                    {
                        printf("左区模式\n");
                        tx_len = build_bed_cmd(write_cmd, 1);
                        printf("tx_len = %d\n", tx_len);
                        ESP_LOG_BUFFER_HEXDUMP(TX_TASK_TAG, write_cmd, tx_len, ESP_LOG_INFO); // 直接打印十六进制数据
                        BED_send(BED_UART_NUM, write_cmd, tx_len);
                        vTaskDelay(5 / portTICK_PERIOD_MS);
                    }
                    if (Bed_Control_State[2] == 1)
                    {
                        printf("右区模式\n");
                        tx_len = build_bed_cmd(write_cmd, 2);
                        printf("tx_len = %d\n", tx_len);
                        ESP_LOG_BUFFER_HEXDUMP(TX_TASK_TAG, write_cmd, tx_len, ESP_LOG_INFO); // 直接打印十六进制数据
                        BED_send(BED_UART_NUM, write_cmd, tx_len);
                        vTaskDelay(5 / portTICK_PERIOD_MS);
                    }
                    if (Bed_Control_State[3] == 1)
                    {
                        printf("左区温度\n");
                        tx_len = build_bed_cmd(write_cmd, 3);
                        printf("tx_len = %d\n", tx_len);
                        ESP_LOG_BUFFER_HEXDUMP(TX_TASK_TAG, write_cmd, tx_len, ESP_LOG_INFO); // 直接打印十六进制数据
                        BED_send(BED_UART_NUM, write_cmd, tx_len);
                        vTaskDelay(5 / portTICK_PERIOD_MS);
                    }
                    if (Bed_Control_State[4] == 1)
                    {
                        printf("右区温度\n");
                        tx_len = build_bed_cmd(write_cmd, 4);
                        printf("tx_len = %d\n", tx_len);
                        ESP_LOG_BUFFER_HEXDUMP(TX_TASK_TAG, write_cmd, tx_len, ESP_LOG_INFO); // 直接打印十六进制数据
                        BED_send(BED_UART_NUM, write_cmd, tx_len);
                        vTaskDelay(5 / portTICK_PERIOD_MS);
                    }
                    if (Bed_Control_State[5] == 1)
                    {
                        printf("左区时间\n");
                        tx_len = build_bed_cmd(write_cmd, 5);
                        printf("tx_len = %d\n", tx_len);
                        ESP_LOG_BUFFER_HEXDUMP(TX_TASK_TAG, write_cmd, tx_len, ESP_LOG_INFO); // 直接打印十六进制数据
                        BED_send(BED_UART_NUM, write_cmd, tx_len);
                        vTaskDelay(5 / portTICK_PERIOD_MS);
                    }
                    if (Bed_Control_State[6] == 1)
                    {
                        printf("右区时间\n");
                        tx_len = build_bed_cmd(write_cmd, 6);
                        printf("tx_len = %d\n", tx_len);
                        ESP_LOG_BUFFER_HEXDUMP(TX_TASK_TAG, write_cmd, tx_len, ESP_LOG_INFO); // 直接打印十六进制数据
                        BED_send(BED_UART_NUM, write_cmd, tx_len);
                        vTaskDelay(5 / portTICK_PERIOD_MS);
                    }
                    if (Bed_Control_State[7] == 1)
                    {
                        printf("指示灯开关\n");
                        tx_len = build_bed_cmd(write_cmd, 7);
                        printf("tx_len = %d\n", tx_len);
                        ESP_LOG_BUFFER_HEXDUMP(TX_TASK_TAG, write_cmd, tx_len, ESP_LOG_INFO); // 直接打印十六进制数据
                        BED_send(BED_UART_NUM, write_cmd, tx_len);
                        vTaskDelay(5 / portTICK_PERIOD_MS);
                    }

                    if (xSemaphore != NULL)
                    {
                        printf("控制完成,释放信号量\n");
                        xSemaphoreGive(xSemaphore);
                    }
                    else
                    {
                        printf("无需重复释放\n");
                    }
                }
                else
                {
                    printf("未获取到信号量\n");

                    bed_tx = 1;
                }
            }
            else
            {
                xSemaphore = xSemaphoreCreateMutex();
                printf("重新创建\n");
            }
            memset(Bed_Control_State, 0, sizeof(Bed_Control_State));
        }
        // 有读取状态命令
        else if (bed_tx == 2)
        {

            printf("有读取状态指令\n");
            printf("开始获取信号量\n");
            if (xSemaphore != NULL)
            {
                if (xSemaphoreTake(xSemaphore, portMAX_DELAY) == pdTRUE)
                {
                    bed_tx = 0;
                    printf("获取信号量成功\n");
                    tx_len = build_bed_cmd(write_cmd, 8);
                    ESP_LOG_BUFFER_HEXDUMP(TX_TASK_TAG, write_cmd, tx_len, ESP_LOG_INFO); // 直接打印十六进制数据
                    BED_send(BED_UART_NUM, write_cmd, tx_len);
                    vTaskDelay(10 / portTICK_PERIOD_MS);
                    if (xSemaphore != NULL)
                    {
                        printf("控制完成,释放信号量\n");
                        xSemaphoreGive(xSemaphore);
                    }
                    else
                    {
                        printf("无需重复释放\n");
                    }
                    bed_rx = 1; // 告诉读任务
                }
                else
                {
                    printf("未获取到信号量\n");
                    bed_tx = 2;
                }
            }
            else
            {
                xSemaphore = xSemaphoreCreateMutex();
                printf("重新创建\n");
            }
        }
        else if (bed_tx > 2)
        {
            printf("开始获取信号量\n");
            if (xSemaphore != NULL)
            {
                printf("xSemaphore != NULL\n");
                if (xSemaphoreTake(xSemaphore, portMAX_DELAY) == pdTRUE)
                {
                    switch (bed_tx)
                    {
                    case 3:
                        printf("已连接路由器\n");
                        tx_len = build_bed_cmd(write_cmd, 9);
                        printf("tx_len = %d\n", tx_len);
                        ESP_LOG_BUFFER_HEXDUMP(TX_TASK_TAG, write_cmd, tx_len, ESP_LOG_INFO); // 直接打印十六进制数据
                        BED_send(BED_UART_NUM, write_cmd, tx_len);
                        vTaskDelay(5 / portTICK_PERIOD_MS);
                        break;
                    case 4:
                        printf("已连接服务器\n");
                        tx_len = build_bed_cmd(write_cmd, 10);
                        printf("tx_len = %d\n", tx_len);
                        ESP_LOG_BUFFER_HEXDUMP(TX_TASK_TAG, write_cmd, tx_len, ESP_LOG_INFO); // 直接打印十六进制数据
                        BED_send(BED_UART_NUM, write_cmd, tx_len);
                        vTaskDelay(5 / portTICK_PERIOD_MS);
                        break;
                    case 5:
                        printf("模组已重置\n");
                        tx_len = build_bed_cmd(write_cmd, 11);
                        printf("tx_len = %d\n", tx_len);
                        ESP_LOG_BUFFER_HEXDUMP(TX_TASK_TAG, write_cmd, tx_len, ESP_LOG_INFO); // 直接打印十六进制数据
                        BED_send(BED_UART_NUM, write_cmd, tx_len);
                        vTaskDelay(5 / portTICK_PERIOD_MS);
                        break;
                    case 6:
                        printf("连接路由器失败\n");
                        tx_len = build_bed_cmd(write_cmd, 12);
                        printf("tx_len = %d\n", tx_len);
                        ESP_LOG_BUFFER_HEXDUMP(TX_TASK_TAG, write_cmd, tx_len, ESP_LOG_INFO); // 直接打印十六进制数据
                        BED_send(BED_UART_NUM, write_cmd, tx_len);
                        vTaskDelay(5 / portTICK_PERIOD_MS);
                        break;
                    case 7:
                        printf("连接服务器失败\n");
                        tx_len = build_bed_cmd(write_cmd, 13);
                        printf("tx_len = %d\n", tx_len);
                        ESP_LOG_BUFFER_HEXDUMP(TX_TASK_TAG, write_cmd, tx_len, ESP_LOG_INFO); // 直接打印十六进制数据
                        BED_send(BED_UART_NUM, write_cmd, tx_len);
                        vTaskDelay(5 / portTICK_PERIOD_MS);
                        break;
                    case 8:
                        printf("成功触发配网应答\n");
                        tx_len = build_bed_cmd(write_cmd, 14);
                        printf("tx_len = %d\n", tx_len);
                        ESP_LOG_BUFFER_HEXDUMP(TX_TASK_TAG, write_cmd, tx_len, ESP_LOG_INFO); // 直接打印十六进制数据
                        BED_send(BED_UART_NUM, write_cmd, tx_len);
                        vTaskDelay(5 / portTICK_PERIOD_MS);
                        break;
                    case 9:
                        printf("版本号回复指令\n");
                        tx_len = build_bed_cmd(write_cmd, 15);
                        printf("tx_len = %d\n", tx_len);
                        ESP_LOG_BUFFER_HEXDUMP(TX_TASK_TAG, write_cmd, tx_len, ESP_LOG_INFO); // 直接打印十六进制数据
                        BED_send(BED_UART_NUM, write_cmd, tx_len);
                        vTaskDelay(5 / portTICK_PERIOD_MS);
                        break;
                    default:
                        printf("无效数据\n");
                        bed_tx = 0;
                        break;
                    }
                    bed_tx = 0;
                    if (xSemaphore != NULL)
                    {
                        printf("控制完成,释放信号量\n");
                        xSemaphoreGive(xSemaphore);
                    }
                    else
                    {
                        printf("无需重复释放\n");
                    }
                }
                else
                {
                    printf("未获取到信号量\n");
                }
            }
            else
            {
                xSemaphore = xSemaphoreCreateMutex();
                printf("重新创建\n");
            }
        }
        vTaskDelay(10 / portTICK_PERIOD_MS); // 为了避免持续占用CPU，适当地加入延时
    }
}

/**
 * @brief
 *
 * @param data 要操作的数组
 * @param sign 标志位，代表要拼装的命令 0：bed_key，1~2左右模式，3~4左右温度，5~6左右时间，7指示灯
 * @return int 返回协议中的数据长度
 */
int build_bed_cmd(char *write_cmd, int sign)
{
    unsigned int checksum = 0; // 记载自己计算的校验和
    int len = 0;
    // 开关
    if (sign == 0)
    {
        write_cmd[1] = 0x04;
        write_cmd[2] = 0x06;
        write_cmd[3] = 0x01;
        write_cmd[4] = Bed_Write.bed_key;
    }
    // 左区模式
    else if (sign == 1)
    {
        write_cmd[1] = 0x05;
        write_cmd[2] = 0x06;
        write_cmd[3] = 0x02;
        write_cmd[4] = 0x01; // 左床
        write_cmd[5] = Bed_Write.left_mode;
    }
    // 右区模式
    else if (sign == 2)
    {
        write_cmd[1] = 0x05;
        write_cmd[2] = 0x06;
        write_cmd[3] = 0x02;
        write_cmd[4] = 0x02; // 右床
        write_cmd[5] = Bed_Write.right_mode;
    }
    // 左区温度
    else if (sign == 3)
    {
        write_cmd[1] = 0x05;
        write_cmd[2] = 0x06;
        write_cmd[3] = 0x03;
        write_cmd[4] = 0x01; // 左床
        write_cmd[5] = Bed_Write.left_settemp;
    }
    // 右区温度
    else if (sign == 4)
    {
        write_cmd[1] = 0x05;
        write_cmd[2] = 0x06;
        write_cmd[3] = 0x03;
        write_cmd[4] = 0x02; // 右床
        write_cmd[5] = Bed_Write.right_settemp;
    }
    // 左区时间
    else if (sign == 5)
    {
        printf("Bed_Write.left_time = %d\n", Bed_Write.left_time);
        write_cmd[1] = 0x05;
        write_cmd[2] = 0x06;
        write_cmd[3] = 0x04;
        write_cmd[4] = 0x01; // 左床
        write_cmd[5] = Bed_Write.left_time;
    }
    // 右区时间
    else if (sign == 6)
    {
        printf("Bed_Write.right_time = %d\n", Bed_Write.right_time);
        write_cmd[1] = 0x05;
        write_cmd[2] = 0x06;
        write_cmd[3] = 0x04;
        write_cmd[4] = 0x02; // 右床
        write_cmd[5] = Bed_Write.right_time;
    }
    // 指示灯
    else if (sign == 7)
    {
        write_cmd[1] = 0x04;
        write_cmd[2] = 0x06;
        write_cmd[3] = 0x06;
        write_cmd[4] = Bed_Write.LED;
    }
    // 读状态
    else if (sign == 8)
    {
        write_cmd[1] = 0x03;
        write_cmd[2] = 0x72;
        write_cmd[3] = 0x00;
    }
    // 已连接路由器
    else if (sign == 9)
    {
        write_cmd[1] = 0x03;
        write_cmd[2] = 0x70;
        write_cmd[3] = 0x01;
    }
    // 已连接服务器
    else if (sign == 10)
    {
        write_cmd[1] = 0x03;
        write_cmd[2] = 0x70;
        write_cmd[3] = 0x02;
    }
    // 模组已重置
    else if (sign == 11)
    {
        write_cmd[1] = 0x03;
        write_cmd[2] = 0x70;
        write_cmd[3] = 0x03;
    }
    // 连接路由器失败
    else if (sign == 12)
    {
        write_cmd[1] = 0x03;
        write_cmd[2] = 0x70;
        write_cmd[3] = 0x04;
    }
    // 连接服务器失败
    else if (sign == 13)
    {
        write_cmd[1] = 0x03;
        write_cmd[2] = 0x70;
        write_cmd[3] = 0x06;
    }
    // 成功触发配网应答
    else if (sign == 14)
    {
        write_cmd[1] = 0x04;
        write_cmd[2] = 0x70;
        write_cmd[3] = 0x05;
        write_cmd[4] = Run_Version;
    }
    // 版本号回复指令
    else if (sign == 15)
    {
        write_cmd[1] = 0x03;
        write_cmd[2] = 0x71;
        write_cmd[3] = Run_Version; // 记得更改
        printf("write_cmd[3] = 0x%02X", write_cmd[3]);
    }
    // 计算校验和
    for (size_t i = 1; i <= write_cmd[1]; i++)
    {
        checksum += write_cmd[i];
    }
    // 只保留累加和的低八位
    checksum &= 0xFF;
    printf("checksum = %02x\n", checksum);
    len = write_cmd[1] + 2; // 数据总长度
    write_cmd[len - 1] = checksum;
    return len;
}
void Publish_WifiTest_Result(esp_mqtt_client_handle_t client, char *topic, bool state)
{
    static const char *TAG4 = "Publish_WifiTest_Result";
    mbedtls_md5_context md5_ctx;
    char wait_encrypt_str[255] = {0};
    unsigned char decrypt[16];
    char decrypt_cs[33];
    cJSON *attributes = cJSON_CreateObject();
    cJSON *content;
    cJSON_AddStringToObject(attributes, "deviceType", "SmartDevice");
    cJSON_AddStringToObject(attributes, "subType", "RDBed");
    cJSON_AddStringToObject(attributes, "deviceMAC", mac_str);
    cJSON_AddStringToObject(attributes, "familyId", "0");
    cJSON_AddStringToObject(attributes, "groupId", "0");
    cJSON_AddStringToObject(attributes, "operate", "reply");
    // content对象
    cJSON_AddItemToObject(attributes, "content", content = cJSON_CreateObject());
    if (state == true)
    {
        cJSON_AddStringToObject(content, "wifitest", "success");
        cJSON_AddStringToObject(content, "wifi_version", g_running_app_version); // 记得改
    }
    else
    {
        cJSON_AddStringToObject(content, "wifitest", "failed");
        cJSON_AddStringToObject(content, "wifi_version", "0");
    }
    char source[] = "Alive";
    cJSON_AddStringToObject(attributes, "source", source);
    cJSON_AddStringToObject(attributes, "version", "v0.1");
    get_time(&system_timestamp);
    ESP_LOGI(TAG1, "The timestamp is %lld \n", system_timestamp);
    char timestamp[14];
    sprintf(timestamp, "%lld", system_timestamp);
    cJSON_AddStringToObject(attributes, "timestamp", timestamp);
    // md5校验
    strcat(wait_encrypt_str, "Alive");
    strcat(wait_encrypt_str, source);
    strcat(wait_encrypt_str, timestamp);
    mbedtls_md5_init(&md5_ctx);
    mbedtls_md5_starts(&md5_ctx);
    mbedtls_md5_update(&md5_ctx, (unsigned char *)wait_encrypt_str, strlen((char *)wait_encrypt_str));
    mbedtls_md5_finish(&md5_ctx, decrypt);
    sprintf(decrypt_cs, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", decrypt[0], decrypt[1], decrypt[2], decrypt[3], decrypt[4], decrypt[5], decrypt[6], decrypt[7], decrypt[8], decrypt[9],
            decrypt[10], decrypt[11], decrypt[12], decrypt[13], decrypt[14], decrypt[15]);
    mbedtls_md5_free(&md5_ctx);
    cJSON_AddStringToObject(attributes, "sign", (char *)decrypt_cs);
    cJSON_AddStringToObject(attributes, "append", cjson_data.append);
    char *ptr = cJSON_Print(attributes);
    // 发布
    int msg_id = esp_mqtt_client_publish(client, topic, ptr, 0, 0, 0);
    ESP_LOGI(TAG4, "sent publish successful, msg_id=%d", msg_id);
    if (ptr != NULL)
    {
        cJSON_free(ptr);
        ptr = NULL;
    }
    cJSON_Delete(attributes);
}

void bed_controltime_task(void *arg)
{
    size_t count = 0;
    nvs_handle_t my_handle;
    esp_err_t err;
    BedControlTime bed_time;
    BedSpread bed_write = {
        .bed_key = 0,
        .left_uptemp = 28,
        .left_downtemp = 28,
        .right_uptemp = 28,
        .right_downtemp = 28,
        .left_mode = 0,
        .left_settemp = 28,
        .left_time = 0,
        .right_mode = 0,
        .right_settemp = 28,
        .right_time = 0,
        .LED = 0};
    while (1)
    {
        // 获取定时参数
        count = 0;
        err = nvs_open(Bed_Storage, NVS_READWRITE, &my_handle);
        err = nvs_get_blob(my_handle, "Bed_Write", &bed_write, &count);
        if (err == ESP_ERR_NVS_NOT_FOUND)
        {
            printf("暂无控制参数\n");
            nvs_close(my_handle);
        }
        err = nvs_get_blob(my_handle, "Bed_Time", &bed_time, &count);

        if (err != ESP_OK)
        {
            printf("暂无定时任务\n");
            nvs_close(my_handle);
        }
        else
        {
            nvs_close(my_handle);
            get_time(&system_timestamp);
            if (bed_time.lefttime_set == 1) // 有左区定时
            {
                printf("system_timestamp = %lld,left_endtime = %lld\n", system_timestamp, bed_time.left_endtime);
                if (system_timestamp - 3 < bed_time.left_endtime && bed_time.left_endtime < system_timestamp + 3) // 如果到达执行时间
                {
                    // 获取床垫开关状态
                    count = sizeof(BedSpread);
                    err = nvs_open(Bed_Storage, NVS_READWRITE, &my_handle);
                    err = nvs_get_blob(my_handle, "Bed_Write", &bed_write, &count);
                    if (err != ESP_OK)
                    {
                        printf("获取开关状态失败\n");
                        printf("Error (%s) erasing NVS!\n", esp_err_to_name(err));
                        bed_write.bed_key = 0;
                    }
                    nvs_close(my_handle);
                    printf("左区到达定时时间\n");
                    bed_time.lefttime_set = 0;
                    // 判断床垫开关当前状态
                    if (bed_write.bed_key == 0)
                    {
                        printf("左区已关闭\n");
                    }
                    else if (bed_write.bed_key == 1)
                    {
                        printf("全床开，关闭左区\n");
                        Bed_Write.bed_key = 3;
                        Bed_Control_State[0] = 1;
                        while (bed_tx != 0)
                        {
                            vTaskDelay(5 / portTICK_PERIOD_MS);
                        }
                        bed_tx = 1;
                        while (bed_tx != 0)
                        {
                            vTaskDelay(5 / portTICK_PERIOD_MS);
                        }
                        printf("左区已关\n");
                    }
                    else if (bed_write.bed_key == 2)
                    {
                        printf("左区开，关闭左区\n");
                        Bed_Write.bed_key = 0;
                        Bed_Control_State[0] = 1;
                        while (bed_tx != 0)
                        {
                            vTaskDelay(5 / portTICK_PERIOD_MS);
                        }
                        bed_tx = 1;
                        while (bed_tx != 0)
                        {
                            vTaskDelay(5 / portTICK_PERIOD_MS);
                        }
                        printf("左区已关\n");
                    }
                    else if (bed_write.bed_key == 3)
                    {
                        printf("右区开，左区未开\n");
                    }
                    // 存储开关状态以及定时任务标志位
                    bed_time.left_starttime = 0;
                    bed_time.left_endtime = 0;
                    err = nvs_open(Bed_Storage, NVS_READWRITE, &my_handle);
                    err = nvs_set_blob(my_handle, "Bed_Write", &Bed_Write, sizeof(BedSpread));
                    if (err != ESP_OK)
                    {
                        printf("存储开关状态失败\n");
                    }
                    err = nvs_set_blob(my_handle, "Bed_Time", &bed_time, sizeof(BedControlTime));
                    if (err != ESP_OK)
                    {
                        printf("存储定时参数失败\n");
                    }
                    err = nvs_commit(my_handle);
                    nvs_close(my_handle);
                }
                else if ((system_timestamp - bed_time.left_endtime > 4) && (system_timestamp > bed_time.left_endtime))
                {
                    printf("左区定时已结束，请重新定时\n");
                    bed_time.lefttime_set = 0;
                    bed_time.left_starttime = 0;
                    bed_time.left_endtime = 0;
                    err = nvs_open(Bed_Storage, NVS_READWRITE, &my_handle);
                    err = nvs_set_blob(my_handle, "Bed_Time", &bed_time, sizeof(BedControlTime));
                    if (err != ESP_OK)
                    {
                        printf("存储定时参数失败\n");
                    }
                    err = nvs_commit(my_handle);
                    nvs_close(my_handle);
                }
            }
            else
            {
                bed_time.lefttime_set = 0;
                bed_time.left_starttime = 0;
                bed_time.left_endtime = 0;
                err = nvs_open(Bed_Storage, NVS_READWRITE, &my_handle);
                err = nvs_set_blob(my_handle, "Bed_Time", &bed_time, sizeof(BedControlTime));
                if (err != ESP_OK)
                {
                    printf("存储定时参数失败\n");
                }
                err = nvs_commit(my_handle);
                nvs_close(my_handle);
            }
            if (bed_time.righttime_set == 1) // 有右区定时
            {
                printf("system_timestamp = %lld,right_endtime = %lld\n", system_timestamp, bed_time.right_endtime);
                if (system_timestamp - 3 < bed_time.right_endtime && bed_time.right_endtime < system_timestamp + 3) // 如果到达执行时间
                {
                    // 获取床垫开关状态
                    count = sizeof(BedSpread);
                    err = nvs_open(Bed_Storage, NVS_READWRITE, &my_handle);
                    err = nvs_get_blob(my_handle, "Bed_Write", &bed_write, &count);
                    if (err != ESP_OK)
                    {
                        printf("获取开关状态失败\n");
                        printf("Error (%s) erasing NVS!\n", esp_err_to_name(err));
                        bed_write.bed_key = 0;
                    }
                    nvs_close(my_handle);
                    printf("右区到达定时时间\n");
                    bed_time.righttime_set = 0;
                    // 判断床垫开关当前状态
                    if (bed_write.bed_key == 0)
                    {
                        printf("右区已关闭\n");
                    }
                    else if (bed_write.bed_key == 1)
                    {
                        printf("全床开，关闭右区\n");
                        Bed_Control_State[0] = 1;
                        Bed_Write.bed_key = 2;
                        bed_tx = 1;
                        while (bed_tx != 0)
                        {
                            vTaskDelay(5 / portTICK_PERIOD_MS);
                        }
                        printf("右区已关\n");
                    }
                    else if (bed_write.bed_key == 2)
                    {
                        printf("左区开，右区未开\n");
                    }
                    else if (bed_write.bed_key == 3)
                    {
                        printf("右区开，左区未开\n");
                        Bed_Control_State[0] = 1;
                        Bed_Write.bed_key = 0;
                        bed_tx = 1;
                        while (bed_tx != 0)
                        {
                            vTaskDelay(5 / portTICK_PERIOD_MS);
                        }
                        printf("右区已关\n");
                    }
                    // 存储开关状态以及定时任务标志位
                    bed_time.right_starttime = 0;
                    bed_time.right_endtime = 0;
                    err = nvs_open(Bed_Storage, NVS_READWRITE, &my_handle);
                    err = nvs_set_blob(my_handle, "Bed_Write", &Bed_Write, sizeof(BedSpread));
                    if (err != ESP_OK)
                    {
                        printf("存储开关状态失败\n");
                    }
                    err = nvs_set_blob(my_handle, "Bed_Time", &bed_time, sizeof(BedControlTime));
                    if (err != ESP_OK)
                    {
                        printf("存储定时参数失败\n");
                    }
                    err = nvs_commit(my_handle);
                    nvs_close(my_handle);
                }
                else if ((system_timestamp - bed_time.right_endtime > 4) && (system_timestamp > bed_time.right_endtime))
                {
                    bed_time.right_starttime = 0;
                    bed_time.right_endtime = 0;
                    printf("右区定时已结束，请重新定时\n");
                    bed_time.righttime_set = 0;
                    err = nvs_open(Bed_Storage, NVS_READWRITE, &my_handle);
                    err = nvs_set_blob(my_handle, "Bed_Time", &bed_time, sizeof(BedControlTime));
                    if (err != ESP_OK)
                    {
                        printf("存储定时参数失败\n");
                    }
                    err = nvs_commit(my_handle);
                    nvs_close(my_handle);
                }
            }
            else
            {
                bed_time.righttime_set = 0;
                bed_time.right_starttime = 0;
                bed_time.right_endtime = 0;
                err = nvs_open(Bed_Storage, NVS_READWRITE, &my_handle);
                err = nvs_set_blob(my_handle, "Bed_Time", &bed_time, sizeof(BedControlTime));
                if (err != ESP_OK)
                {
                    printf("存储定时参数失败\n");
                }
                err = nvs_commit(my_handle);
                nvs_close(my_handle);
            }
        }

        vTaskDelay(2000 / portTICK_PERIOD_MS);
    }
}
// if (bed_rx == 0) // 这时无主动发送指令
// {
//     printf("rx_task in\n");
//     printf("bed_rx = %d\n", bed_rx);
//     const int rxBytes = uart_read_bytes(BED_UART_NUM, data, RX_BUF_SIZE, 100);
//     if (rxBytes > 0)
//     {
//         data[rxBytes] = 0;
//         ESP_LOGI(RX_TASK_TAG, "Read %d bytes: '%s'", rxBytes, data);
//         ESP_LOG_BUFFER_HEXDUMP(RX_TASK_TAG, data, rxBytes, ESP_LOG_INFO);
//     }
// }
// else if (bed_rx == 1)
// {
//     vTaskDelay(100 / portTICK_PERIOD_MS);
// }